面試官:應用上線後Cpu使用率飆升如何排查?

語言: CN / TW / HK

大家好,我是飄渺。

上次面試官問了個問題:應用上線後Cpu使用率飆升如何排查?

其實這是個很常見的問題,也非常簡單,那既然如此我為什麼還要寫呢?因為上次回答的時候我忘記將執行緒PID轉換成16進位制的命令了。

所以我決定再重溫一遍這個問題,當然貼心的我還給大家準備好了測試程式碼,大家可以實際操作一下,這樣下次就不會忘記了。

模擬一個高CPU場景

```java public class HighCpuTest { public static void main(String[] args) { List cpus = new ArrayList<>();

    Thread highCpuThread = new Thread(()->{
        int i = 0;
        while (true){
            HignCpu cpu = new HignCpu("Java日知錄",i);

            cpus.add(cpu);
            System.out.println("high cpu size:" + cpus.size());
            i ++;
        }
    });
    highCpuThread.setName("HignCpu");
    highCpuThread.start();
}

} ```

在main方法中開啟了一個執行緒,無限構建HighCpu物件。

java @Data @AllArgsConstructor public class HignCpu { private String name; private int age; }

準備好上面的程式碼,執行HighCpuTest,然後就可以開始一些列的操作來發現問題原因了。

排查步驟

第一步,使用 top 找到佔用 CPU 最高的 Java 程序

```shell 1. 監控cpu執行狀,顯示程序執行資訊列表 top -c

  1. 按CPU使用率排序,鍵入大寫的P P ```

image-20220627165915946

第二步,用 top -Hp 命令檢視佔用 CPU 最高的執行緒

上一步用 top命令找到了那個 Java 程序。那一個程序中有那麼多執行緒,不可能所有執行緒都一直佔著 CPU 不放,這一步要做的就是揪出這個罪魁禍首,當然有可能不止一個。

執行top -Hp pid命令,pid 就是前面的 Java 程序,我這個例子中就是 16738 ,完整命令為:

top -Hp 16738,然後鍵入P (大寫p),執行緒按照CPU使用率排序

執行之後的效果如下

image-20220627165953456

查到佔用CPU最高的那個執行緒 PID 為 16756

第三步,檢視堆疊資訊,定位對應程式碼

通過printf命令將其轉化成16進位制,之所以需要轉化為16進位制,是因為堆疊裡,執行緒id是用16進製表示的。(我當時就是忘記這個命令了~)

shell [root@review-dev ~]# printf "%x\n" 16756 4174

得到16進位制的執行緒ID為4174。

通過jstack命令檢視堆疊資訊

shell jstack 16738 | grep '0x4174' -C10 --color

image-20220627170218909

如上圖,找到了耗CPU高的執行緒對應的執行緒名稱“HighCpu”,以及看到了該執行緒正在執行程式碼的堆疊。

最後,根據堆疊裡的資訊,定位到對應死迴圈程式碼,搞定。

小結

cpu使用率飆升後如何排查這個問題不僅面試中經常會問,而且在實際工作中也非常有用,大家最好根據上述步驟實際操作一下,這樣才能記得住記得牢。

我正在參與掘金技術社群創作者簽約計劃招募活動,點選連結報名投稿