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

我正在參與掘金技術社區創作者簽約計劃招募活動,點擊鏈接報名投稿