Java “Tomcat服务器无响应”;http-nio-80-Acceptor-0“;

Java “Tomcat服务器无响应”;http-nio-80-Acceptor-0“;,java,spring-boot,tomcat,garbage-collection,Java,Spring Boot,Tomcat,Garbage Collection,我有一个SpringBoot(1.5.8.RELEASE)应用程序,运行5GB内存。当我点击API,请求返回它抛出的大量数据时 > Apr 30, 2020 2:01:34 PM org.apache.catalina.core.StandardWrapperValve invoke SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handl

我有一个SpringBoot(1.5.8.RELEASE)应用程序,运行5GB内存。当我点击API,请求返回它抛出的大量数据时

> Apr 30, 2020 2:01:34 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded] with root cause
上述异常是预期的,因为数据量很大,应用程序内存不足。但如果我用相同的请求点击API,返回大量数据,我的应用程序就会抛出以下异常,应用程序就会失去响应,每次我都需要重新启动它。但是,如果我再次使用API,请求返回的数据量会减少,那么它就可以正常工作

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "http-nio-80-Acceptor-0"
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Tomcat]]" java.lang.OutOfMemoryError: GC overhead limit exceeded
Apr 30, 2020 2:09:22 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded] with root cause
java.lang.OutOfMemoryError: GC overhead limit exceeded

为什么它会对同一个请求抛出不同的异常?我使用VisualVm分析了内存,在处理请求后,内存立即变得清晰,我确保没有内存泄漏。这与我正在使用的
org.apache.tomcat.jdbc.pool.DataSource()
有关吗?

当GC开销太大以至于应用程序几乎所有的时间都花在GC(98%)内务管理活动上时,就会发生这种情况。因此,应用程序的正常功能受到阻碍,变得没有响应。JVM没有继续这样做,而是发出了关于这个问题的错误警告

通常发生在以下情况:

  • 在应用程序的正常处理过程中创建的对象的堆大小受到限制
  • 内存泄漏(根据VisualVM,似乎没有内存泄漏)
  • 我已经看到当对象和其他数据的累积大小超过堆内存的80%时,GC的开销周期和几乎所有的CPU。这导致了一个GC,它不能回收太多,导致另一个GC等等

    简言之,如果您确定没有内存泄漏,那么首先应该尝试:

  • 增加堆的大小
  • 并尝试找出应用程序在运行用例时创建的对象。你能减少这个数字吗?我记得,有一个用例是读取JSON文件。与其读取文件并在堆中创建数百万个JSON对象,还可以对文件进行流式处理(就像在输入流中一样),然后读取、创建对象、对其进行操作(并在计算后丢弃)并移动到下一个对象

    您可以指定另一个GC算法(如其他地方所指定的),但这并不能解决本例中的问题。问题似乎是应用程序和OOM没有响应,而不仅仅是应用程序响应的延迟更高。
    希望对您有所帮助。

    您会遇到以下错误:
    java.lang.OutOfMemoryError:超出了GC开销限制

    当JVM花费太多时间执行垃圾收集并且只能回收很少的堆空间时,就会发生此错误

    根据Java文档,默认情况下,JVM配置为抛出 如果Java进程将98%以上的时间用于 每次运行中仅恢复不到堆的2%时。在里面 换句话说,这意味着我们的应用程序几乎耗尽了所有资源 可用内存和垃圾收集器花费了太多时间 试图清理它,但多次失败

    解决方案:
    • 增加堆大小,例如-Xmx1g
    • 可以通过添加选项禁用限制检查 -XX:-usegcoveredlimit到命令行
    您可以在tomcat/bin/setenv.sh文件中设置jvm env config,如下所示:

    CATALINA_OPTS="-Djava.awt.headless=true -Xms2048m -Xmx2048m  -XX:-UseGCOverheadLimit"
    

    但是为什么它会对同一个请求抛出不同的异常呢?两个请求都给出了
    GC开销限制超过了
    第二个请求给出了线程http-nio-80-Acceptor-0中的异常。因此,我认为这与tomcatits jvm环境配置问题有关。。。。您可以在
    tomcat/bin/setenv.sh
    处设置此配置。。。您的根本原因是
    GC开销限制超出了
    当您离开堆空间时,tomcat会给出此错误
    http-nio-80-Acceptor-0
    我可以尝试增加堆大小,但它不应该一直抛出相同的异常吗?如果问题是堆对于对象等太有限,那么您的应用程序会创建增加堆这将解决问题。另一方面,如果出现内存泄漏或其他一些问题,那么堆限制将再次达到。我建议您尝试增加堆并检查这是否解决了问题。这就是第一步。巨大的数据将需要巨大的堆。时期如果你可以返回部分,分页,等等-这样做,否则就没有神奇的子弹。