线上服务线程数过高的问题定位与解决方法
问题现象:
富仁小站线上API服务在年3月21号下午出现问题,不能提供对外服务,导致线上设备和相关业务流程中断
临时解决方案:
为了防止服务中断时间过久,重启服务
问题定位:
在3月21号之后的几天连续观察服务的线程和内存变化1、观察服务线程数的变化:
pstree-pthreadNum.txt复制代码PS:因为线上服务过多,直接在控制台执行命令,容易出现刷屏,直接将线程树打印到文本中进行调查
2、拿到线程树之后,查找线程树中线程数最多的进程ID,然后通过:
ps-ef
grepjava复制代码的方式进行了解具体的线程数过多的服务。
3、在定位到具体出问题的服务之后,通过下面的命令进入到容器
dockerexec-itcontainer_name/bin/bash复制代码4、进入到服务的容器之后,通过jstat命令来查看当前服务的内存GC情况,以便了解是否是因为服务的GC过高导致出现了OOM的问题
jstat-gcutilpid复制代码
等待上面的命令执行完毕后,观察当前的gc情况,其中:
s0、s1、E三个表示的是内存中年轻代的占比
O表示的是内存中的老年代占比
YGC表示的是年轻代GC发生的次数
YGCT表示的是年轻代GC发生的总耗时
FGC表示的全GC发生的次数
FGCT表示的是全GC发生总耗时
当FGC次数过高,耗时过长,服务中断的可能性越高,但是通过线程查看,服务并没有发生过高的FGC的情况
5、通过jstat并没有发现什么大的问题,那么就需要获取服务的内存堆栈进行分析了。内存堆栈的分析可以使用jmap的方式进行分析,也可以通过MemoryAnalysis工具进行分析。首先我们将内存堆栈导出:
jmap-dump:live,format=b,file=heap.binpid复制代码或者
jmap-dump:live,format=b,file=heap.hprofpid复制代码我们此处使用第二种方式,通过内存分析工具来分析,能更加的清楚
6、通过内存堆栈的分析我们只能看见问题发生在了和线程池有关的地方,然后其中对象数top3中主要是Thread、String和LinkedBlokingQueue,那么我们可以初步定位问题应该我们的线程池使用的时候出现了问题,我们再继续查看Thread的具体对象信息,发现有很多事在延时任务上,这部分代码是我们自己写的代码,其他的都是第三方框架,咱们暂时先不要