1. 程式人生 > >Linux(2)---記錄一次線上服務 CPU 100%的排查過程

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% 排查的步驟整理

2、線上服務 CPU 100%?一鍵定位 so easy!






如果一個人充滿快樂,正面的思想,那麼好的人事物就會和他共鳴,而且被他吸引過來。同樣,一個人老帶悲傷,倒黴的事情也會跟過來。
​                                                      ——在自己心情低落的時候,告誡自己不要把負能量帶給別人。(大校10)