使用jstack排查线上故障:高CPU占用

  • Post author:
  • Post category:其他




1. 前言

一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环。我们以当时出现的实际故障为例,来介绍怎么定位和解决这类问题。



2. 排查步骤

思路:找出tomcat 进程中使用CPU最高、时间最长的线程,分析堆栈信息,定位问题。



2.1 先拿到tomcat进程ID

ps –ef | grep tomcat 

记录下tomcat应用进程的ID: 30027(我拿到的是这个值)

这里按照我们排查故障的思维习惯,是直接怀疑我们部署的tomcat应用服务出现故障。如果你不确定,比如怀疑是同时部署到这台机的监控程序或其他进程引起的问题,那可以先使用top命令查看到底是哪个进程占用CPU过高,再拿这个PID走下面的流程。



2.2 拿到CPU占用最高、时间最长的线程ID

# 显示进程号为30027的进程信息,CPU、内存占用率等
top -H -p 3002

在这里插入图片描述

当然这一步你也可以使用以下这个命令,显示特定PID下全部线程列表,以定位到是哪个线程占用CPU时间最高:

当然这一步你也可以使用以下这个命令,显示特定PID下全部线程列表,以定位到是哪个线程占用CPU时间最高:



2.3 将需要的线程ID转换为16进制格式

printf "%x\n" 1852

得到结果:73c(这里我只查看了1852这个线程ID)



2.4 打印线程的堆栈信息

jstack 30027 |grep 73c -A 30

得到如下信息:

"pool-1617252-thread-1" prio=10 tid=0x00007f76a00e5800 nid=0x73c runnable [0x00007f7658e61000]
   java.lang.Thread.State: RUNNABLE
        at java.util.Random.next(Random.java:139)
        at java.util.Random.nextDouble(Random.java:394)
        at java.lang.Math.random(Math.java:695)
        at com.xxx.xxx.utils.Rand.randomNoSame(Rand.java:100)
        at com.xxx.xxx.videos.GetVideoListService.getUserPullDownVirtualPageResult(GetVideoListService.java:275)
        at com.xxx.xxx.videos.GetVideoListService.getVideoList(GetVideoListService.java:94)
        at sun.reflect.GeneratedMethodAccessor1123.invoke(Unknown Source)

找到出现问题的代码了!



3. 总结

最后,总结下排查CPU故障的方法和技巧有哪些:


  • top命令

    :Linux命令。可以查看实时的CPU使用情况。也可以查看最近一段时间的CPU使用情况。

  • ps命令

    :Linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前CPU使用情况。属于当前状态的采样数据。

  • jstack

    :Java提供的命令。可以查看某个进程的当前线程栈运行情况。根据这个命令的输出可以定位某个进程的所有线程的当前运行状态、运行代码,以及是否死锁等等。