天天看點

CPU扛不住了前言正文後記最後

前言

這是一篇根據生活編撰的一個小故事,講述了一個比較少見的伺服器問題——CPU使用率過高。文中包含了從CPU過高告警,到一步步定位到導緻CPU過高的代碼的追溯過程。

前面是小故事,算是場景引入,如無興趣可繞過從後記部分開始。鄭重聲明:故事很小,如有雷同,純屬虛構。

正文

“快看看,CPU使用率爆紅了,看着要扛不住了!”小P打電話吼道,小P是伺服器的監控。

“什麼鬼?”,正準備睡覺的小碼爬了起來,小碼是系統的開發者。

“我一個沒多少計算的應用服務怎麼就扛不住了,一定是其他服務導緻的!”小碼嘀咕道。

開機!

登入VPN!

打開finalShell,ssh伺服器一氣呵成。

看着自己娴熟的操作,小碼的嘴角漏出了一絲絲驕傲。

top # Linux系統下,可以查詢目前正在運作任務,包含CPU使用率、記憶體等資訊,類似于Windows任務管理器

啪,回車的聲音依然清脆,仿佛在迎合着小碼的自信。

“我丢@@@”CPU使用率排行第一個是一個Java應用,程序ID 136018,“不會吧...”,嘴角微微抖了一下。

ps -aux | grep xxx-manager.jar #說明:查詢服務的程序,xxx-manager.jar是服務包名,端口也可

果然,136018!136018!136018... 通過多次仔細比對CPU使用率top1的程序号和自己服務的程序号,确定是小碼負責的服務!小碼後背一下涼了半截。

“趕快排查排查,趁服務還沒當機”

top -H -p 136018 #說明:-H開啟線程模式,-p指定服務程序号

然後找到瘋狂占用CPU的線程ID: 136086

printf %x 136086 #說明:此指令是将10進制轉換為16進制,因為jstack中線程ID是16進制。136086轉換後是0x21396

jcmd Thread.print > jstack.out # 說明:jcmd是jdk自帶的分析工具,此指令會将目前jvm棧資訊輸出到jstack.out檔案中。

最後,vim進入jstack.out檔案,搜尋0x21396,找到線程棧資訊,就看到了業務代碼。

業務僞代碼

for(int i = 0; i < 65535, i++){

methodB(i)

}

void methodB(int i){

for(int j = 0 ; j < 10086; j++){

...

"這...",循環調用了一個方法methodB,該方法裡面還有個循環,類似于循環嵌套循環。外層周遊次數6萬+,嵌套循環次數1萬+,MD這一個來回就是6億多次。再看看接口調用方,是頁面初始化加載...

“我......”,小碼看着祖傳代碼陷入沉思,“難怪号稱宇宙第一塊的CPU都扛不住了”。

正在思考解決辦法的時候...,“醒醒...小碼!你電話響了!”,同僚叫醒了呼呼大睡的小碼。

看着午睡寶上面一灘口水,小碼心裡慶幸到:“哦,原來是一場夢啊!”。

“電話!小碼!你的電話!!”

來不及去回味殘餘的一絲絲僥幸,小碼趕快看了看手機:【13個未接來電,來自客戶老總】。

“我丢@@@”,不會真扛不住了吧...

後記

本文通過一個小故事,講述了一個比較少見的問題-CPU使用率過高的問題,包含了發現CPU過高告警,到找到導緻CPU過高的代碼的追溯過程。

定位步驟:

1.首先檢視CPU高占用率的程序号,根據程序号查詢CPU高占用率的線程ID,使用top指令。

2.快照目前服務端棧資訊,線程ID轉為16進制在棧資訊檔案裡查找對應線程棧,即可找到導緻CPU瘋狂飙升的代碼了。

3.然後根據需要,進行業務或者算法上面的調整優化。

最後