问题发现
通过线上Grafana监控发现某服务 JVM-Thread线程异常高,并且发现每天都在持续飙升,如下。![](https://img.haomeiwen.com/i6819280/3e645f5541f7b1f8.png)
可看到jvm线程少说几百,多则几千甚至过万,并且如果服务不重启,可发现线程数随着时间的推移持续上升,并且没有下降趋势,因此可以看出服务中一定有某些编码没有使用线程池,在持续的new Thread()创建线程,导致线程数飙升。
定位问题
由于线上服务是云部署,在我们公司开发是没有权限登录服务终端查看应用jvm情况,包括线程信息,所以给定位带来的很多困难。
起初我们定位问题方案是通过测试环境开启Spring Actuator监控,通过访问 /actuator/threaddump获取运行时的线程dump信息,相当于直接在终端执行jstack命令获取jvm线程信息。然后在测试环境观察线程数量变化,通过几次的对比去判断哪些线程名在持续飙升,进而定位问题。
但一段时间过后,发现测试环境的线程数量变化并不是很明显,需要等很长一段时间才有可能看到明显的效果。所以放弃治疗。![](https://img.haomeiwen.com/i6819280/dda49c1f34a6dccc.png)
无奈。就开始实现二套方案,直接找运维配合导出线上实例机器上的jvm-thread dump文件,然后直接分析thread-dump文件定位问题,文件大致内容如下。
![](https://img.haomeiwen.com/i6819280/75040415593a3ec1.png)
这里分析的dump文件大致有480多k,如果一行行看起来也比较不清晰,所以直接上工具。
IBM JCA 工具 https://www.ibm.com/support/pages/ibm-thread-and-monitor-dump-analyzer-java-tmda
载入文件如下:
![](https://img.haomeiwen.com/i6819280/9bf33ff6592f2f8f.png)
![](https://img.haomeiwen.com/i6819280/287a4294892afed6.png)
at com.qcloud.cos.http.IdleConnectionMonitorThread.run(IdleConnectionMonitorThread.java:26)
打开IDA源代码如下。
![](https://img.haomeiwen.com/i6819280/3a5312de67715fc8.png)
![](https://img.haomeiwen.com/i6819280/82c783bfd1127b9e.png)
![](https://img.haomeiwen.com/i6819280/e8b82d78b9df5f7d.png)
![](https://img.haomeiwen.com/i6819280/4f50fc52cf79e7e5.png)
![](https://img.haomeiwen.com/i6819280/e61fd12115b23e6b.png)
![](https://img.haomeiwen.com/i6819280/bf85bda02be4d7a8.png)
解决方案
1.多例模式
每次创建client之后,在使用结束进行手动显示的shutdown掉Cilent客户端。![](https://img.haomeiwen.com/i6819280/cd968f1a56190302.png)
2.单例模式
将CosClient 声明到Spring IOC容器中为单利模式,全局使用一个CosClient客户端进行调用。在调用结束之后无需手动进行shutdown调用。例![](https://img.haomeiwen.com/i6819280/94b06031210efc51.png)
网友评论