Linux(2)---記錄一次線上服務 CPU 100%的排查過程
Linux(2)---記錄一次線上服務 CPU 100%的排查過程
當時產生CPU飆升接近100%的原因是因為專案中的websocket時時斷開又重連導致CPU飆升接近100% 。如何排查的呢 是通過日誌
輸出錯誤資訊: 得知websocket時時重新
連線的資訊,然後找到原因 解決了。
當然這裡幸好能通過日誌大致分析出原因 那麼我就在思考如果日誌沒有告訴任何資訊 但線上CPU還是接近100%那麼如何排查呢。所以學習了下排查過程。
通過查閱資料並實踐後,這裡總結了兩種辦法。第一種部落格滿天飛的方法 通過top命令
第二種非常好用 通過大牛寫的指令碼排查
一、top命令排查
1、命令四部曲
(1)通過top命令,知道CPU最高的程序
top
(2)具體檢視java中哪個執行緒一直在佔用cpu時間(這裡我的java程序號是: 8752)
#java程序ID進行CPU佔用排查(sort -rn 以數值的方式進行逆序排列)
ps -mp 8752 -o THREAD,tid,time | sort -rn | more
(3)根據2中查詢到的CPU最高的排序中的結果,找出幾個佔用cpu時間比較高的TID,將執行緒ID轉換為16進位制
printf "%x\n" TID
(4)再使用jstack命名查詢是哪個執行緒
#8752是java程序ID,6669是第三步執行緒ID轉換的16進位制 jstack 8752 |grep 6669 -A 30
2、案例
(1) top命令
(2)ps命令
(3)printf命令
(4)jstack命令
二、show-busy-java-threads.sh指令碼
上面的 4 步雖然能夠排查問題,但總的還是還是太繁瑣耗時了,於是有大神寫了個指令碼,在有問題的時候一鍵定位,能夠妙計找到問題。這個作者是一個叫淘寶的oldratlee 同學。
1、指令碼使用說明
怎麼使用呢?可以看作者的GitHub地址中的文件說明,而且裡面也有相應指令碼:Github
我們可以把這個git專案clone到Linux環境中(說明:目前這個指令碼只支援linux環境)
git clone https://github.com/oldratlee/useful-scripts.git #將下面下載到linux環境中。
這裡也整理一些該指令碼的常用命令
show-busy-java-threads.sh
# 從 所有的 Java程序中找出最消耗CPU的執行緒(預設5個),打印出其執行緒棧。
show-busy-java-threads.sh -c <要顯示的執行緒棧數>
show-busy-java-threads.sh -c <要顯示的執行緒棧數> -p <指定的Java Process>
# -F選項:執行jstack命令時加上-F選項(強制jstack),一般情況不需要使用
show-busy-java-threads.sh -p <指定的Java Process> -F
show-busy-java-threads.sh -s <指定jstack命令的全路徑>
# 對於sudo方式的執行,JAVA_HOME環境變數不能傳遞給root,
# 而root使用者往往沒有配置JAVA_HOME且不方便配置,
# 顯式指定jstack命令的路徑就反而顯得更方便了
show-busy-java-threads.sh -a <輸出記錄到的檔案>
show-busy-java-threads.sh -t <重複執行的次數> -i <重複執行的間隔秒數>
# 預設執行一次;執行間隔預設是3秒
##############################
# 注意:
##############################
# 如果Java程序的使用者 與 執行指令碼的當前使用者 不同,則jstack不了這個Java程序。
# 為了能切換到Java程序的使用者,需要加sudo來執行,即可以解決:
sudo show-busy-java-threads.sh
2、案例說明
為了反應真實性,找了個能讓CPU飆升100%的程式碼打包成jar在線上跑,這裡採用定時任務讓它跑起來。
//java 正則表示式回溯造成 CPU 100%
@Service
public class GateTrigger {
@Scheduled(fixedDelay = 1 * 1000)
public void startSummary() {
String[] patternMatch = {"([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)",
"([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)+([+\\-/*])+([\\w\\s]+)"};
List<String> patternList = new ArrayList<String>();
patternList.add("Avg Volume Units product A + Volume Units product A");
patternList.add("Avg Volume Units / Volume Units product A");
patternList.add("Avg retailer On Hand / Volume Units Plan / Store Count");
patternList.add("Avg Hand Volume Units Plan Store Count");
patternList.add("1 - Avg merchant Volume Units");
patternList.add("Total retailer shipment Count");
for (String s : patternList) {
for (int i = 0; i < patternMatch.length; i++) {
Pattern pattern = Pattern.compile(patternMatch[i]);
Matcher matcher = pattern.matcher(s);
System.out.println(s);
//CPU飆升根源
if (matcher.matches()) {
System.out.println("Passed");
} else
System.out.println("Failed;");
}
}}
}
(1)top命令 發現CPU的確飆升了
(2)執行指令碼
bash show-busy-java-threads.sh
(3)看後臺執行結果
......
發現一下子就定位問題了,不得不說缺少很方便,快捷。
參考
1、Java死鎖排查和Java CPU 100% 排查的步驟整理
如果一個人充滿快樂,正面的思想,那麼好的人事物就會和他共鳴,而且被他吸引過來。同樣,一個人老帶悲傷,倒黴的事情也會跟過來。
——在自己心情低落的時候,告誡自己不要把負能量帶給別人。(大校10)