记一次 Java 项目 CPU 占用久高不下故障处理

事件背景

公司对接了新系统,代码变动很大,项目也很急,于是在上线之后 Zabbix 不时就告警,提示 CPU 使用过载,告警消息类似如下:

一开始以为是系统停机升级,所有人都等着使用系统,导致系统处理压力增加的缘故,所以并没有太关注,但后来发现一直都在出这个问题,就觉得不对了。于是开始着手对问题开始处理。

排查问题

1. 由于是 CPU 使用率问题导致,所以可以先定位,到底是哪个服务导致,于是使用 top 命令查看:

top

结果如下:(使用 shift + m 可以对通过内存使用排序,方便我们找到问题进程)

当然,我这里已经是正常状态了,故障的时候没有来得及截图!当时 %CPU 我记得是 398。

可以大致猜想到,肯定是代码中某个函数问题,导致阻塞在那里了。

2. 查看该进程的开启的线程信息使用 ps 命令:

ps -mp 6506 -o THREAD,tid,time

当然,6506 是这个有问题进程的 PID 注意改成你自己的。tid 是线程 ID,time 则是该线程运行的时间,附带一张故障当时的截图:

可以看到 1816 和 1817 这两个线程 CPU 使用 94% 以上,并且运行了 7 分钟了。

3. 由于 jstack 中线程 ID 是 16 进制的,所以我们需要转成 16 进制来协助我们查询问题:

printf "%x
" 1816
printf "%x
" 1817

结果如下:

4. 通过 JDK 自带的 jstack 工具获取运行时候的信息:

jstack 6506 > /tmp/1.txt

注意 6506 换成自己之前 Java 进程的 PID。我们把它重定向到 /tmp 目录下面的 1.txt 文件,方便我们查询。

5. 查询异常:

此时我们可以 vim 刚刚的 1.txt 文件,搜索我们转换成 16 进制的 tid:

我们可以将这个内容丢给对应的开发,让他们取查看指定的代码就行了,作为运维,我们所能做的差不多就这些。

项目最终在开发对代码进行调整以后恢复,原因为请求第三方接口,然后等待在那里,出了问题。

最后,由于个人不是开发,又不是大牛,可能文中有些地方写的不对,希望大家能够在评论中补充出来。我好及时调整以免误导看到的朋友。

原文地址:https://www.cnblogs.com/Dy1an/p/11983244.html