笔者最近在排查一次线上故障时, 发现一个很奇怪的现象: 线上服务启动时,没有任何流量和访问,服务cpu使用率莫名妙达到25%。 一开始不为其然,认为是项目中使用了公司自研的中间件, 导致了cpu使用率偏高。后面通过排查发现,其实是java守护线程使用方式出了问题,谨以此文章记录下排查过程,以及反思结果。
1. 查看服务器cpu 使用最高进程id
在服务器中使用top 命令,查看当前cpu使用率排名靠前的进程id
sh> top
image.png
从上图中可以看到 java 进程占据了cpu将近25%的使用率
2. 找出对应的哪个子线程占据了主要的使用时间 top -H -p pid #查看异常的线程
从第一步可以看出,当前cpu使用率最高的进程 id 是1
> top -H -p 1
image.png
从上图找出来了对应的子线程的 id 为66
3. 将进程id 转为 16进制 printf "%x\n" tid
# printf "%x\n" 66
42
4. 通过jstack 命令查找出异常线程
> jstack 1|grep 0x42 -A 30
image.png
5 修改代码
从4步骤找出来异常代码是TopicSender.java 36行。
至此,异常代码定位出来, 接下来就是如何修改代码。
源代码
image.png
源代码很简单,就是一个守护线程,不停循环的运行, 没有什么异常逻辑, 百思其解了好久,想要不让线程每运行一次就调用一次Thread.sleep()。我这边设定了先试着 sleep 500ms 看看效果
image.png
然后就是部署,查验效果后,cpu使用率下降至2%
image.png
最后的结语
一次简单的问题排查,让我对java的线程使用更加熟练, 同时也学会了如何去排查线上服务cpu使用率偏高的手段。 同时也再次给我一次警醒。故障往往是因为不在意的小问题,及时发现问题, 及时解决问题。