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) ```