寫作目的
最近看牛客網發現了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%的情況

定位問題
定位高負載的程序服務
首先使用top指令确認伺服器的具體情況,定位到高負載的程序服務,如下圖所示,我發現PID為929的服務CPU那欄高達86%,初步定位到是這個PID為929服務有問題。
定位到具體的線程
通過上面我們可以定位的程序的ID為929,接下來我們要定位到該程序的哪個線程占用CPU比較高,使用如下指令,其中929為程序ID。
top -Hp 929
此時可以定位到是線程1141占用CPU比較高。
将線程号(1141)轉為16進制(後面用)
printf '%x\n' 1141
定位線程調用棧
通過以下指令把定位的程序線程調用棧儲存下來,其中929為程序ID
jstack 929 > 929.log
下圖為929.log的部分資訊,其中我們知道程序中線程号(十進制1141,十六進制475)占用CPU比較高,我們可以通過線程ID的十六進制定位到線程,然後根據調用棧定位資訊,發現定位到我們自己寫的代碼,然後在捋一捋自己代碼的邏輯就好。