线程创建过多导致服务内存溢出

  • 一次jvm内存溢出问题排查


一次jvm内存溢出问题排查

首先看下问题原因:

linux内存 java 一直不释放 linux jvm内存溢出_高并发


上图的意思是获取直接内存失败,然后jvm建议减少堆的大小,或者减小每个线程的大小,或者增加系统内存观察下线程的状态:

linux内存 java 一直不释放 linux jvm内存溢出_问题排查_02


目前总共产生了十三万个线程池(代码编写存在问题,一般情况下不会有这么多线程池),且统计了一下,存在十三万的线程都处于阻塞状态开始使用jstack -l pid 观察运行中的状态:

linux内存 java 一直不释放 linux jvm内存溢出_问题排查_03


目前的线程是阻塞状态,且在等待一个锁

分析
从以上的状态来看,高并发情况下,程序一直在重复的创建线程池并运行任务,但是每个线程都阻塞在一个条件上了,不是高并发情况却不会存在这个问题;
这种情况存在一种可能性:消费问题,由于系统瓶颈导致大量线程获取不到锁,从而阻塞;
结果:
由于linux系统对进程的同时打开文件数的限制,导致高并发情况下的文件读写速度跟不上,引发了线程的积压,适量增大系统的limit数量:
vim /etc/security/limits.conf

*                soft    nofile          65536
*                hard    nofile          65536
root             soft    nofile          327680
root             hard    nofile          327680
*                soft    nproc           327680
*                hard    nproc           327680

由于是老代码,这里存在一个问题,这里的线程使用是存在问题的,不应该创建那么多的线程去执行任务,使用队列加线程池的方式是最佳的解决办法。如果存在任务积压,可以通过拒绝策略指定处理方式,而不是需要排查堆栈日志找问题;