先讲下问题来源,前一段时间线上服务器负载高的吓人,做为一台只部署了tomcat的应用服务器,平时load average 也就在零点几的水平,忽然达到十几真是让人惊了个呆(⊙ˍ⊙),生怕服务器分分钟宕掉啊。html
赶忙找问题发生缘由吧,我之前没有遇到过这类问题,没啥经验可谈,首先服务器上top
下,发现最耗cpu的就是咱们的应用服务器,如图:java
我立刻想到的是咱们有异步处理的多线程程序,是否是哪一个程序死锁了或者一直跑着,不释放。因而查看了最近修改的代码,也没有发现那里可能会发生死循环,那干脆打印下堆栈看看到底都有什么线程在跑着吧。到jdk的bin路径下 用jstack pid >xxx.stack
命令打印堆栈内容。linux
快1MB的内容,真的无法去找,都是一些TIMED_WAITING
,WAITING
这些能够先不用去看,优先级高的应该是那些RUNNABLE
的,由于都已经等待了,就消耗不到cpu了啊。看了半天也没看出啥名堂,最后在其余博客上取取经,发现了实用的技巧。tomcat
具体思路:服务器
首先要找到哪几个线程在占用cpu,以后再经过线程的id值在堆栈文件中查找具体的线程,看看出来什么问题。多线程
OK,实战开始,第一个命令异步
ps -mp pid -o THREAD,tid,time
其中pid
换成要查看的进程的id值,这个命令的做用就是打印出进程下有哪几个线程在跑,而且分别占用cpu多长时间。.net
对ps
不熟悉话,能够在linux下查看man ps
文档,看看具体那几个命令的做用线程
-p
的后面跟着要显示的进程的id号,-m
的意思是显示这个进程下的全部线程-o
的意思是格式化要输出的内容code
经过上边这个命令,显示出一堆线程,经过筛选以后发现了几个占用cpu很长的线程
%CPU | TID | TIME |
---|---|---|
17.3 | 16172 | 12:18:58 |
79.9 | 16275 | 2-08:49:22 |
19.8 | 418 | 12:16:02 |
32.6 | 13071 | 12:17:14 |
这下可算找到罪魁祸首了,看第二个线程cpu占用的吓人,而且占用时间也是高的离谱,我记住它了( *⊙~⊙)。
第二个命令,将找到的线程id号转成十六进制
printf "%x\n" tid
这个很简单,就不解释了,获得结果是3f93
。
以后就是在最初打印的堆栈信息中查找这个线程,Bingo!
请原谅,把关键信息注释上了,哈哈。找到这个线程,能够看到具体出问题的代码行了,对就是我注释那几个代码行,以后就在源码中查找下,发现真的有一个死循环在那里(⊙﹏⊙)b,好了既然找到了那就fix掉就能够了。
在一次上线以后服务器的状况:
又健健康康的啦~~~。
结尾再费点唾沫,查找好cpu的线程时一共有四个,其实那三个我也找了,发现是咱们本身建立的线程池,因此不是问题啦。
参考文章: 线上应用故障排查之一:高CPU占用