先講下問題來源,前一段時間線上服務器負載高的嚇人,做爲一臺只部署了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佔用