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