问题
某应用经常出现Full GC和Young GC,需要找出问题
解决
- 对于GC或OOM问题,可以将出现问题的集群中的一个实例下线,获取其heap dump文件,进行分析
- 使用mat(Memory Analyzer Tools)工具(可去官网下载1.8.1及以下版本,超过这个版本需要JDK11及以上)打开dump文件分析:
- 点击“Leak Suspects”,如图可以看到"java.lang.Thread"这个实例有677个,加载的线程占用的内存有874m左右;
- 再点击下图的小齿轮按钮,会展示“Thread_overview”线程概览信息,如下图一可以看到这些线程主要来自这个类“XXXManager”(一个业务逻辑java类);也可以点击找到使用方也能找到这个类:
-
进入这个类,发现使用的是自定义线程池,线程池的各项参数是写死的,线程创建过多会占用cpu资源,同时也会占用堆空间内存,一个线程默认占用空间1M,几百个线程就会占用空间几百M;
且这里的线程池阻塞队列没有限制,线程池内的线程在获取到一个任务后,需要执行时间较长,会导致workQueue里积压的任务越来越多,大量任务的积压导致机器的内存使用不停的飙升,最后导致OOM
- 点击“Leak Suspects”,如图可以看到"java.lang.Thread"这个实例有677个,加载的线程占用的内存有874m左右;
- 解决方法:
- 将代码中写死的线程池参数转移至服务配置中心,代码中通过读取对应配置文件中参数进行线程池配置。这样的好处是在出现问题时,在配置中的配置文件中修改配置即可,实现参数热更新
- 调整该线程池参数,合理配置:
效果
- JMX thread线程数量max从大约740降到至236,降低约68%
- JMX thread线程数量avg从大约724降到至232,降低约68%
- JMX Young gc count数量avg从大约2.5降到至1.25,降低约50%
- JMX Young gc time耗时max从大约652降到至250,降低约61%
-
-
- JMX Young gc time耗时avg从大约440降到至150,降低约66%
-
-
- 2024-07-13发布上线之后到目前为止不再出现full gc情况