首页 > 其他分享 >一次排查Jvm线程飙升问题的经历

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

时间:2023-02-23 10:33:21浏览次数:46  
标签:Jvm dump 定位问题 如下 排查 线程 jvm new

问题发现

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

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


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

定位问题

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

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

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

一次排查Jvm线程飙升问题的经历_多例模式_02

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

一次排查Jvm线程飙升问题的经历_多例模式_03


这里分析的dump文件大致有480多k,如果一行行看起来也比较不清晰,所以直接上工具。

IBM JCA 工具 ​​https://www.ibm.com/support/pages/ibm-thread-and-monitor-dump-analyzer-java-tmda​

载入文件如下:




一次排查Jvm线程飙升问题的经历_测试环境_04




从可视化工具可以很清晰看到 Object.wait 等待锁有487个线程,正常情况,一个应用如果某时刻的wait等待锁的线程数量大于几十个就大概率说明服务有问题了,更何况这里出现了几百个,很显然是不正常的,于是我们随便找一个wait状态的线程看下详细信息如下。




一次排查Jvm线程飙升问题的经历_测试环境_05






at com.qcloud.cos.http.IdleConnectionMonitorThread.run(IdleConnectionMonitorThread.java:26)




打开IDA源代码如下。




一次排查Jvm线程飙升问题的经历_多例模式_06





通过分析,得知在new COSClient()的时候每次new,都会 new 一个IdleConnectionMonitorThread 线程,因此如果使用多例模式每次使用COS Client的时候随着时间的推移就会有大量的空闲线程被创建出来,所以就出现了一开始的问题。UML依赖图如下。




一次排查Jvm线程飙升问题的经历_多例模式_07








一次排查Jvm线程飙升问题的经历_多例模式_08







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







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







一次排查Jvm线程飙升问题的经历_测试环境_11




解决方案

1.多例模式



每次创建client之后,在使用结束进行手动显示的shutdown掉Cilent客户端。




一次排查Jvm线程飙升问题的经历_多例模式_12




2.单例模式



将CosClient 声明到Spring IOC容器中为单利模式,全局使用一个CosClient客户端进行调用。在调用结束之后无需手动进行shutdown调用。例




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




附件工具

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


标签:Jvm,dump,定位问题,如下,排查,线程,jvm,new
From: https://blog.51cto.com/u_13146445/6080619

相关文章

  • 【FAQ】获取Push Token失败,如何进行排查?
    一、 获取PushToken的方式获取PushToken有两种方式:一种是调用getToken方法向Push服务端请求Token,当getToken方法返回为空时,Token可通过onNewToken方法返回,因此需要实现o......
  • JVM基础学习笔记
    JDK、JRE、JVM的区别:三层的嵌套关系。JDK>JRE>JVM1、JDK:编译Java源码,生成Java字节码。/bin包含:(1)、java:启动JVM,运行Java程序(2)、javac:Java的编译器,将Java源......
  • AnyShare客户端问题排查
    手动安装客户端服务1、cmd窗口创建anyshareservice服务先打开服务,检查服务状态,并开启尝试手动开启以管理员身份打开命令提示符,删除已有Anyshare服务scquery查询所有......
  • 线程属性
    线程的属性实现线程创建的时候(pthread_create)指定线程属性的初始化和销毁线程属性的结构:  如果线程设置了分离状态这个属性,那么可以在线程结束时,主线程不用调用pth......
  • 线程终止
    线程终止的方式:1.主动终止a.线程运行函数中调用returnb.线程中调用pthread_exit函数2.被动终止线程可以被同一进程的其他线程取消,其他线程调用pthrea......
  • 【JVM】001-JVM的运行机制
    【JVM】001-JVM的运行机制1、JVM(JavaVirtualMachine)是用于运行Java字节码的虚拟机。2、JVM包括:一套字节码指令集+一组程序寄存器+一个虚拟机栈+一个虚拟机堆+......
  • 线程
    线程和进程概念进程:数据隔离,资源分配的最小单位,可以利用多核,操作系统调度,开启关闭切换时间消耗大multiprocessing如何开启进程startjoin进程有数据不安全问......
  • 创建多线程方式3:实现Callable接口 改造下载图片案例
    packagecom.Test;importorg.apache.commons.io.FileUtils;importjava.io.File;importjava.io.IOException;importjava.net.URL;importjava.util.concurrent.*;//开......
  • Java多线程技能-方法介绍
    java多线程技能技术点:线程的启动如何使线程暂停如何使线程停止线程的优先级线程安全相关的问题方法currentThread()currentThread()方法可返回代码段正在被哪......
  • 多线程 龟兔赛跑案例
    packagecom.Java;publicclassRaceimplementsRunnable{//胜利者privatestaticStringwinner;@Overridepublicvoidrun(){for(inti=0......