引言
最近項目部門反應有個系統特別卡頓,很多頁面都打不開了,開發人員告訴我說最近沒有進行代碼升級,我登錄到對應的服務器上執行了top命令,發現cpu飆升到100%,對於這種問題我們應該快速的定位到問題,否則會影響線上系統的正常作業。
對於造成這種問題的可能原因,迅速的在頭腦中閃過四種情況:
1、某個接口響應時間超長,並且可能被頻繁調用
2、產生了過大的對象,造成頻繁FGC
3、代碼出現死循環
4、線程出現死鎖
下面是小編的定位問題的步驟:
1)top
2)top -Hp 2848
3)printf "%x" 2925
4)jstack 2848 | grep 0xb6d -C50 --color
第一、執行top命令,結果如下
我們根據top結果發現,有java進程CPU佔用超過100%,說明這個進程中的代碼出現問題了
第二、執行top -Hp 2848 查看該pid詳情
從上面結果,我們基本可以排除產生大對象的情況,因爲如果有大對象產生,這個時候的結果應該是有多個進程CPU佔用都會超過80%,其中有多個進程在在進行GC,從而造成CPU飆升。
第三 執行 printf "%x" 2925 轉換爲 十六進制
第四 執行 jstack 2848 | grep 0xb6d -C50 --color 查看具體的信息,由於我們項目使用daemon用戶啓動,所以我執行的命令爲
/sbin/runuser -s /bin/bash daemon -c "jstack 2848 | grep 0xb6d -C50 --color"
上圖中紅色的nid就是我們查看的進行對應的詳細代碼信息,從上面我們就可以很快的定位到具體的代碼行,我們系統此處代碼是一個統計的方法,由於前端傳遞的時間跨度非常大,並且多個人在頻繁的刷新造成系統卡死。
注意:我們執行jstack的時候,執行用戶需要和進程啓動用戶一直,否則會提示下面錯誤
Unable to open socket file: target process not responding or HotSpot VM not loaded
The -F option can be used when the target process is not responding
********************下面我們分析一下 代碼執行過程中產生 "超大對象" 出現的現象***************************************
1、top
2、 執行命令 top -Hp 23002
我們發現有很多的進程cpu佔用都查過了90%,這種情況很可能是多個進程在進行FGC,爲了驗證這種情況我們執行下面命令
3、jstat -gcutil 23002 2000 5
上面命令是 輸出該進程在jvm中的佔用情況 每2000毫秒執行一次 一共執行5次
從輸出信息可以看出,Eden區內存佔用100%,Old區內存佔用99.97%,Full GC的次數高達170次,並且頻繁Full GC,Full GC的持續時間也特別長,平均每次Full GC耗時5.93秒(1009.445/170)。根據這些信息,基本可以確定是程序代碼上出現了問題,可能存在不合理創建對象的地方
4、將上面的對應的四個線程號十進制轉換爲 十六進制
5、執行命令 jstack 23002 |grep "0x59dd" -C50 --color 查看對應的線程信息
由上圖可見,cpu使用率高的線程都在GC task,JVM的GC線程一直在佔用大量CPU
6、也可以執行命令jstack -l 23002 >/data1/23002.statck 將對應的進程號的棧信息輸入到指定目錄
7、在23002.statck中就行過濾查詢
7、過濾搜索一下 我們項目名稱,就可以看到具體的代碼位置
8、然後根據具體的代碼分析一下,出現 問題的具體原因
小結
線上出現cpu100%問題需要我們在最短的是時間內解決該問題,其中最重要的是我們能快速的定位到問題出現的具體代碼位置,然後我們才能在最短的時間內解決,對於一些不是很重要的統計功能,我們可以先暫停該功能,首先保證主要流程正常使用,待服務恢復正常以後,我們在 優化具體的代碼。