天天看點

Java服務CPU100%異常排查實踐總結

寫作目的

最近看牛客網發現了CPU 100% 怎麼辦這個問題,這個問題的重點是定位和解決,會用到Linux和java的的很多指令,是以寫篇部落格記錄和總結一下。

CPU 100%複現

之前有一個1核的騰訊雲伺服器,正好就不用搞虛拟機了。

寫一個死循環Service

@Service
public class Cpu100Service {

  public void cpu100() {
    int a = 10;
    while (a < 100) {
      System.out.println(LocalDateTime.now().toString());
    }
  }
}      

在controller中調用該Service就複現了。

@Autowired
  private Cpu100Service cpu100Service;
  
@GetMapping("/cpu100")
  public Object getWhileList() {
    cpu100Service.cpu100();
    return 1;
  }      

在伺服器上啟動服務後調用死循環的接口,則CPU出現負載100%的情況

Java服務CPU100%異常排查實踐總結

定位問題

定位高負載的程序服務

首先使用top指令确認伺服器的具體情況,定位到高負載的程序服務,如下圖所示,我發現PID為929的服務CPU那欄高達86%,初步定位到是這個PID為929服務有問題。

Java服務CPU100%異常排查實踐總結

定位到具體的線程

通過上面我們可以定位的程序的ID為929,接下來我們要定位到該程序的哪個線程占用CPU比較高,使用如下指令,其中929為程序ID。

top -Hp 929      
Java服務CPU100%異常排查實踐總結

此時可以定位到是線程1141占用CPU比較高。

将線程号(1141)轉為16進制(後面用)

printf '%x\n' 1141      
Java服務CPU100%異常排查實踐總結

定位線程調用棧

通過以下指令把定位的程序線程調用棧儲存下來,其中929為程序ID

jstack 929 > 929.log      

下圖為929.log的部分資訊,其中我們知道程序中線程号(十進制1141,十六進制475)占用CPU比較高,我們可以通過線程ID的十六進制定位到線程,然後根據調用棧定位資訊,發現定位到我們自己寫的代碼,然後在捋一捋自己代碼的邏輯就好。

參考