美文网首页
一次排查Jvm线程飙升问题的经历

一次排查Jvm线程飙升问题的经历

作者: 淡v漠 | 来源:发表于2021-02-22 15:00 被阅读0次

    问题发现

    通过线上Grafana监控发现某服务 JVM-Thread线程异常高,并且发现每天都在持续飙升,如下。

    可看到jvm线程少说几百,多则几千甚至过万,并且如果服务不重启,可发现线程数随着时间的推移持续上升,并且没有下降趋势,因此可以看出服务中一定有某些编码没有使用线程池,在持续的new Thread()创建线程,导致线程数飙升。

    定位问题

    由于线上服务是云部署,在我们公司开发是没有权限登录服务终端查看应用jvm情况,包括线程信息,所以给定位带来的很多困难。

    起初我们定位问题方案是通过测试环境开启Spring Actuator监控,通过访问 /actuator/threaddump获取运行时的线程dump信息,相当于直接在终端执行jstack命令获取jvm线程信息。然后在测试环境观察线程数量变化,通过几次的对比去判断哪些线程名在持续飙升,进而定位问题。

    但一段时间过后,发现测试环境的线程数量变化并不是很明显,需要等很长一段时间才有可能看到明显的效果。所以放弃治疗。

    无奈。就开始实现二套方案,直接找运维配合导出线上实例机器上的jvm-thread dump文件,然后直接分析thread-dump文件定位问题,文件大致内容如下。


    这里分析的dump文件大致有480多k,如果一行行看起来也比较不清晰,所以直接上工具。
    IBM JCA 工具 https://www.ibm.com/support/pages/ibm-thread-and-monitor-dump-analyzer-java-tmda
    载入文件如下:
    从可视化工具可以很清晰看到 Object.wait 等待锁有487个线程,正常情况,一个应用如果某时刻的wait等待锁的线程数量大于几十个就大概率说明服务有问题了,更何况这里出现了几百个,很显然是不正常的,于是我们随便找一个wait状态的线程看下详细信息如下。
    at com.qcloud.cos.http.IdleConnectionMonitorThread.run(IdleConnectionMonitorThread.java:26)
    
    打开IDA源代码如下。 通过分析,得知在new COSClient()的时候每次new,都会 new 一个IdleConnectionMonitorThread 线程,因此如果使用多例模式每次使用COS Client的时候随着时间的推移就会有大量的空闲线程被创建出来,所以就出现了一开始的问题。UML依赖图如下。

    解决方案

    1.多例模式
    每次创建client之后,在使用结束进行手动显示的shutdown掉Cilent客户端。
    2.单例模式
    将CosClient 声明到Spring IOC容器中为单利模式,全局使用一个CosClient客户端进行调用。在调用结束之后无需手动进行shutdown调用。例

    附件工具

    https://download.csdn.net/download/qianyan0365/15419859

    相关文章

      网友评论

          本文标题:一次排查Jvm线程飙升问题的经历

          本文链接:https://www.haomeiwen.com/subject/dpzhfltx.html