2023.07.20 20:01:38線上一個服務發生了CPU過高的告警,
看告警信息當前的CPU使用率已經達到了82.65%,問題已經很嚴重,趕緊開始排查起來。來複盤下如何排查這類問題,
一、排查方法
1、找到cpu過高的進程ID
收到告警後,第一件事要做的就是找到CPU過高的程序的線程id(pid),可以使用jps或ps -ef |grep java兩個命令均可,
1.1、jps
使用jps命令
jps
得到下面的結果
也就是進程ID是6。
再看使用ps的結果
1.2、ps
使用ps命令
ps -ef |grep java
得到下面的結果
可以看到進程ID也是6。
當然除了上面兩個命令,還可以使用top,也可以很快找到CPU過高的服務進程ID。
我們已經知道了cpu過高的服務進程ID是6,但僅知道進程ID是無用的,需要進一步知道這個進程中哪些線程佔用CPU過高。
2、找到cpu過高的線程ID
這裏使用的是top命令
top -Hp 6
得到的結果如下
可以看到線程1110 1125 1112 1121等佔用CPU過高,基本都在80%,基本可以斷定就是這些線程在佔用CPU。
找到佔用CPU過高的線程後,就要看下相應的堆棧信息。
1.3、打印進程堆棧
使用jstack命令,jstack命令可以打印出進程的堆棧,通過堆棧信息可以分析到線程的執行情況,
jstack -l 6
可以看到很多類似這樣的信息,這些信息中有一個很重要的那就是nid=0x11,這個是代表的線程ID,聰明的你也一定知道這裏是16進制,和剛纔使用top -Hp命令看到的不一樣,那裏是10進制的。
爲了找到線程佔用cpu過高的堆棧,需要把線程ID做一次進制轉換,既由10進制轉換爲16進制,
例,1110--》0x456 1125--》0x465
以0x465爲例,在堆棧中查找相應的線程堆棧,
1.4、查找線程堆棧
使用0x465查找其對應的線程堆棧
可以看到線程0x465的線程狀態是RUNNABLE,而且看到了很多正則的調用,繼續往下看,找到了調用的代碼,
最後分析是由於死循環引起的線程佔用CPU過高。
上面是我把文件下載下來進行的查找,那如何生成堆棧文件,可以使用下面的命令
jstack -l 6 > dump.txt
生成後下載到本地即可。
如果線上環境無法下載,則只能通過命令進行查找
jstack -l 6 | grep -A 10 0x465
這樣便可以看到相應的內容了。
二、fastthread
有沒有覺得使用jstack命令導出文件後自己分析很麻煩,沒事有工具,可以使用fastthread。
其網址是:https://fastthread.io/
將jstack或者其他工具dump的堆棧文件上傳到該網站同樣可以分析出結果。
將剛纔的文件上傳後,得到分析報告,由於是分析CPU過高,重點看cpu threads即可。
可以看到nativeId:1125即對應top -Hp出的線程ID,這裏fastThread已經進行了進制轉換,無需手動操作了,很貼心。點擊查看完整的堆棧信息即可分析出相應的問題。
三、總結
一般程序CPU過高,大多數和死循環有關,分析此類問題的一般步驟是,
1、使用jps/ps -ef |grep java/top等命令找到進程ID,即pid;
2、使用top -Hp pid 找到進程中佔用CUP的線程ID;
3、使用jstack打印堆棧;
4、使用線程ID在堆棧中找到對應的線程堆棧;
5、分析線程堆棧,找到問題;
參考:
(7條消息) jstack命令解析_fightingD&W的博客-CSDN博客
Linux命令之Grep——文本搜索 - 閱讀清單 - 騰訊雲開發者社區-騰訊雲 (tencent.com)
推薦閱讀
花了半天時間,使用spring-boot實現動態數據源,切換自如