記錄一次線上服務CPU飆高問題

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)

 

推薦閱讀

因爲一條DDL,差點搞掛整個系統,這次真的長了教訓

一次性掌握innodb引擎如何解決幻讀和不可重複讀

花了半天時間,使用spring-boot實現動態數據源,切換自如

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章