CPU 使用率過高和 jvm old 占用過高排查過程
報(bào)警
cpu使用率過高報(bào)警,接近100%
后續(xù)又來了jvm old過高報(bào)警
排查過程
首先打開監(jiān)控平臺(tái)看報(bào)警節(jié)點(diǎn)的cpu使用情況

登錄服務(wù)器找到占用 cpu過高線程堆棧信息
①通過?top?命令找到占用cpu最高的?pid[進(jìn)程id]

定位到pid是 1469
②通過?top -Hp pid?查看進(jìn)程中占用cpu過高的?tid[線程id]
③通過?printf ?pid |grep tid?把線程id轉(zhuǎn)化為十六進(jìn)制
④通過?jstack pid | grep tid -A 30?定位線程堆棧信息
占用cpu過高的線程有兩個(gè),其中一個(gè)是打印異常日志的(會(huì)new 對象),還有g(shù)c線程
打印異常堆棧

這個(gè)占用cpu根據(jù)堆棧信息就可以定位,看下代碼,可以發(fā)現(xiàn)new 對象,且打印全棧信息

其中ExceptionUtils.getFullStackTrace(e) 屬于commons.lang包

可以發(fā)現(xiàn)上面兩個(gè)方法會(huì)創(chuàng)建很多對象且打印堆棧信息占用內(nèi)存
gc線程

可以發(fā)現(xiàn)占用cpu過高的線程進(jìn)行大量的gc
1. 通過?jstat -gcutil pid 時(shí)間間隔?查看 jc ?信息

可以發(fā)現(xiàn)伊甸園區(qū)和老年代都已經(jīng)滿了,且進(jìn)行了大量的FGC
指標(biāo)介紹
S0:年輕代第一個(gè)幸存區(qū)(survivor)使用容量占用百分比
S1:年輕代第二個(gè)幸存區(qū)(survivor)使用容量占用百分比
E:年輕代伊甸園區(qū)(eden)使用容量占用百分比
O:老年代使用容量占用百分比
P:perm代使用容量占用百分比
YGC:從應(yīng)用程序啟動(dòng)到當(dāng)前采樣時(shí)年輕代gc的次數(shù)
YGCT:從應(yīng)用程序啟動(dòng)到當(dāng)前采樣時(shí)年輕代gc的時(shí)間
FGC:從應(yīng)用程序啟動(dòng)到當(dāng)前采樣時(shí)老年代gc的次數(shù)
FGCT:從應(yīng)用程序啟動(dòng)到當(dāng)前采樣時(shí)老年代gc的時(shí)間
GCT:從應(yīng)用程序啟動(dòng)到當(dāng)前采樣時(shí)gc總耗時(shí)
2. 導(dǎo)出dump文件,使用jdk自帶的jvisualvm.exe分析
使用?jmap -dump:format=b,file=name.dump pid?導(dǎo)出dump文件,一般dump文件會(huì)比較大【我的這個(gè)2.94G】,然后下載【可以用 sz name.dump】到本地用jvisualvm【jdk自帶的,在bin目錄下】分析
首先看下dump文件的概要

看看這些大對象都是什么

發(fā)現(xiàn)前面幾個(gè)大對象都和 ElastaicSearchStatusException對象有關(guān),然后這個(gè)管理平臺(tái)用到es的地方只有一處,就是做數(shù)據(jù)漏斗,記錄廣告檢索在哪些步驟過濾掉,方便產(chǎn)品和運(yùn)營查看廣告被過濾的原因,然后翻開代碼

其中 RestClientFactory.getRestClient().search(searchRequest)的 search方法一步一步跟進(jìn),發(fā)現(xiàn)拋ElasticSearchStatusException的地方

其中parseResponseException方法會(huì)拋出ElasticSearchStatusException異常,至于這兩個(gè)地方具體是哪個(gè)步驟拋的,可以繼續(xù)研究es代碼判斷或者 遠(yuǎn)程debug判定,我這里先不管了,反正我們能知道es出問題了
其實(shí)正是因?yàn)檫@里拋異常才會(huì)導(dǎo)致創(chuàng)建大量對象,因?yàn)楫惓T谏厦嫣岬降拇蛴‘惓H罩镜牡胤揭矔?huì)創(chuàng)建對象,老年代占用過高,導(dǎo)致大量fgc
但es這里為何會(huì)有異常?
我登錄到es的管理平臺(tái)查看es的索引,發(fā)現(xiàn)有的索引沒有創(chuàng)建,索引的創(chuàng)建是有任務(wù)去創(chuàng)建并實(shí)時(shí)寫入數(shù)據(jù)的,發(fā)現(xiàn)那個(gè)任務(wù)已經(jīng)停了。
處理過程
找到相關(guān)的任務(wù)重新啟動(dòng),并找任務(wù)停止的原因,修復(fù),并把丟失的索引創(chuàng)建并修復(fù)數(shù)據(jù)
在異常日志打印那最好加入流控【用Guava.RateLimiter控制】
小結(jié)
cpu占用過高排查思路
top 查看占用cpu的進(jìn)程 pid
top -Hp pid 查看進(jìn)程中占用cpu過高的線程id ?tid
printf '%x/n' tid 轉(zhuǎn)化為十六進(jìn)制
jstack pid |grep tid的十六進(jìn)制 -A 30 查看堆棧信息定位
jvm old區(qū)占用過高排查思路
top查看占用cpu高的進(jìn)程
jstat -gcutil pid 時(shí)間間隔 查看gc狀況
jmap -dump:format=b,file=name.dump pid ?導(dǎo)出dump文件
用visualVM分析dump文件
