程序員不小心把服務(wù)器CPU打到100%,展示教科書(shū)排查過(guò)程
你們沒(méi)發(fā)現(xiàn)我最近的原創(chuàng)原創(chuàng)少了很多嘛,一是最近花了很多時(shí)間做視頻,本來(lái)我寫文章就是利用周末的兩天時(shí)間,但是現(xiàn)在基本上兩天都要拍攝剪輯了,盡管請(qǐng)了小伙伴做字幕,還是得耗費(fèi)大量時(shí)間在拍攝和剪輯上。
所以我只能利用工作日熬一下才能寫出來(lái)了,這周因?yàn)橐l(fā)布,本來(lái)是沒(méi)排期寫文章的,你們也看到了我發(fā)了兩個(gè)視頻嘛。
但是今天我一發(fā)布就嚇尿了….
事情是這樣的…..
我和小組伙伴最近負(fù)責(zé)的系統(tǒng)今天上線了,因?yàn)樯婕暗降臉I(yè)務(wù)特別多所以選擇白天發(fā)布,怕出問(wèn)題找不到對(duì)應(yīng)的負(fù)責(zé)人。
看到3點(diǎn)25那個(gè)full gc沒(méi),我發(fā)布上去一分鐘不到就瘋狂GC,我當(dāng)時(shí)就嚇尿了,馬上點(diǎn)了回滾按鈕。

而且我發(fā)現(xiàn)cpu幾乎在我發(fā)布的瞬間,直接打到了峰值。

所幸只發(fā)布了一臺(tái),我緊張的望向了周圍,發(fā)現(xiàn)周圍的同事沒(méi)注意到我,我頓時(shí)沒(méi)那么緊張了,拿起桌上用剩下的紙巾搽掉了我鬢角馬上留下的汗水。
我其實(shí)已經(jīng)知道大概是什么問(wèn)題了,無(wú)非就是死循環(huán),或者大對(duì)象什么的。
但是我還是想找個(gè)人承擔(dān)這個(gè)鍋。
我馬上找到三歪,我問(wèn)他:你剛才是不是點(diǎn)過(guò)我的系統(tǒng)?
他說(shuō):對(duì)啊,我剛才點(diǎn)了,我本來(lái)就經(jīng)常使用你的系統(tǒng),咋了?(剛好正中下懷嘻嘻)
我說(shuō)過(guò)多少次啊,叫你不要亂點(diǎn),這已經(jīng)不是第一次了,現(xiàn)在把我的系統(tǒng)點(diǎn)壞了,怎么辦?都怪你。
他:委屈巴巴一副要哭的樣子。
我:誒,算了算了,下次注意哈,我去排查下什么情況,看看你點(diǎn)壞了哪里。
他:丙哥真好,丙哥真棒,丙哥我愛(ài)你。
總算是找到背鍋俠了,我就開(kāi)始排查問(wèn)題吧。
注:以下代碼都是偽代碼,為了還原排查過(guò)程
一般CPU100%瘋狂GC,都是死循環(huán)的鍋,那怎么排查呢?
先進(jìn)服務(wù)器,用top -c 命令找出當(dāng)前進(jìn)程的運(yùn)行列表
按一下 P 可以按照CPU使用率進(jìn)行排序
顯示Java進(jìn)程 PID 為 2609 的java進(jìn)程消耗最高

然后我們需要根據(jù)PID 查出CPU里面消耗最高的進(jìn)程
使用命令 top -Hp 2609 找出這個(gè)進(jìn)程下面的線程,繼續(xù)按P排序
可以看到 2854 CPU消耗最高

2854是十進(jìn)制的,我們需要轉(zhuǎn)換為十六進(jìn)制,轉(zhuǎn)換結(jié)果:b26
接下來(lái)就需要導(dǎo)出我們的進(jìn)程快照了,看看這個(gè)線程做了啥
- jstack -l 2609 > ./2609.stack
再用grep查看一下線程在文件里做了啥
- cat 2609.stack |grep 'b26' -C 8
我這里就隨便定位一個(gè),基本上這樣查都可以定位到你死循環(huán)的那個(gè)類,那一行,這里你還可以在jstack出來(lái)的文件中看到很多熟悉的名詞,至于是啥,你們留言告訴我好了,就當(dāng)是個(gè)課后作業(yè)了。

我寫了個(gè)偽代碼,看看當(dāng)時(shí)我為啥會(huì)寫出這個(gè)死循環(huán),對(duì)了當(dāng)時(shí)我上線的是預(yù)發(fā),也是后臺(tái)系統(tǒng)非線上的,雖然都是自己在玩,但是大家還是要引以為戒。

我當(dāng)時(shí)寫了個(gè)代碼準(zhǔn)備去查出數(shù)據(jù)庫(kù)的數(shù)據(jù),訂正下日期,仔細(xì)看沒(méi)問(wèn)題,但是我忘了數(shù)據(jù)庫(kù)的偏移值自己去計(jì)算了,因?yàn)橐郧岸际强蚣埽约号R時(shí)寫的就沒(méi)管。
導(dǎo)致每次都能查出10個(gè)數(shù)據(jù),在最后判斷的時(shí)候就一直true不退出了,其實(shí)最后會(huì)退出,但是得循環(huán)很多次。
我這里退出的邏輯比較取巧,就是想著最后一次查詢肯定跟我的頁(yè)數(shù)不一樣,那就是最后一頁(yè)了,那我就處理完退出。
結(jié)果沒(méi)想到也是個(gè)坑了。
大家寫的時(shí)候也要注意很多小坑,這次我就給個(gè)demo順便帶大家溫習(xí)一下線上故障的排查,下次我可能搞點(diǎn)內(nèi)存泄露,集群宕機(jī)什么的故障,這樣就有素材了呀。
如果真出問(wèn)題,第一時(shí)間找個(gè)三歪這樣的背鍋俠,排查過(guò)程自己去電腦上操作一下,最近有點(diǎn)忙,準(zhǔn)備寫個(gè)分布式鎖的文章,如何?
我是敖丙,一個(gè)在互聯(lián)網(wǎng)茍且偷生的工具人。