今天斷斷續(xù)續(xù)的收到管理平臺(tái)的異常報(bào)警市埋,cpu占用過(guò)高和jvm old占用過(guò)高肌蜻,這個(gè)時(shí)候趕緊去排查原因互墓,下面記錄了我的排查過(guò)程,可能里面還有不正確的地方蒋搜,歡迎各位大佬指正篡撵,也歡迎大家關(guān)于類似的案例一起交流判莉,下面就看我關(guān)于這次排查的過(guò)程把
報(bào)警
- cpu使用率過(guò)高報(bào)警,接近100%
- 后續(xù)又來(lái)了jvm old過(guò)高報(bào)警
排查過(guò)程
- 首先打開監(jiān)控平臺(tái)看報(bào)警節(jié)點(diǎn)的cpu使用情況
- 登錄服務(wù)器找到占用 cpu過(guò)高線程堆棧信息
①通過(guò) top 命令找到占用cpu最高的 pid[進(jìn)程id]
定位到pid是 1469
②通過(guò) top -Hp pid 查看進(jìn)程中占用cpu過(guò)高的 tid[線程id]
③通過(guò) **printf pid |grep tid ** 把線程id轉(zhuǎn)化為十六進(jìn)制
④通過(guò) jstack pid | grep tid -A 30 定位線程堆棧信息
占用cpu過(guò)高的線程有兩個(gè)育谬,其中一個(gè)是打印異常日志的(會(huì)new 對(duì)象)券盅,還有g(shù)c線程
打印異常堆棧
這個(gè)占用cpu根據(jù)堆棧信息就可以定位,看下代碼斑司,可以發(fā)現(xiàn)new 對(duì)象渗饮,且打印全棧信息
其中ExceptionUtils.getFullStackTrace(e) 屬于commons.lang包
可以發(fā)現(xiàn)上面兩個(gè)方法會(huì)創(chuàng)建很多對(duì)象且打印堆棧信息占用內(nèi)存
gc線程
可以發(fā)現(xiàn)占用cpu過(guò)高的線程進(jìn)行大量的gc
- 通過(guò) 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í)
- 導(dǎo)出dump文件宿刮,使用jdk自帶的jvisualvm.exe分析
使用 jmap -dump:live,format=b,file=name.dump pid 導(dǎo)出dump文件互站,一般dump文件會(huì)比較大【我的這個(gè)2.94G】,然后下載【可以用 sz name.dump】到本地用jvisualvm【jdk自帶的僵缺,在bin目錄下】分析
首先看下dump文件的概要
看看這些大對(duì)象都是什么
發(fā)現(xiàn)前面幾個(gè)大對(duì)象都和 ElastaicSearchStatusException對(duì)象有關(guān)胡桃,然后這個(gè)管理平臺(tái)用到es的地方只有一處,就是做數(shù)據(jù)漏斗磕潮,記錄廣告檢索在哪些步驟過(guò)濾掉翠胰,方便產(chǎn)品和運(yùn)營(yíng)查看廣告被過(guò)濾的原因,然后翻開代碼
其中 RestClientFactory.getRestClient().search(searchRequest)的 search方法一步一步跟進(jìn)自脯,發(fā)現(xiàn)拋ElasticSearchStatusException的地方
其中parseResponseException方法會(huì)拋出ElasticSearchStatusException異常之景,至于這兩個(gè)地方具體是哪個(gè)步驟拋的,可以繼續(xù)研究es代碼判斷或者 遠(yuǎn)程debug判定膏潮,我這里先不管了锻狗,反正我們能知道es出問(wèn)題了
其實(shí)正是因?yàn)檫@里拋異常才會(huì)導(dǎo)致創(chuàng)建大量對(duì)象,因?yàn)楫惓T谏厦嫣岬降拇蛴‘惓H罩镜牡胤揭矔?huì)創(chuàng)建對(duì)象焕参,老年代占用過(guò)高轻纪,導(dǎo)致大量fgc
但es這里為何會(huì)有異常?
我登錄到es的管理平臺(tái)查看es的索引叠纷,發(fā)現(xiàn)有的索引沒(méi)有創(chuàng)建刻帚,索引的創(chuàng)建是有任務(wù)去創(chuàng)建并實(shí)時(shí)寫入數(shù)據(jù)的,發(fā)現(xiàn)那個(gè)任務(wù)已經(jīng)停了涩嚣。
處理過(guò)程
- 找到相關(guān)的任務(wù)重新啟動(dòng)崇众,并找任務(wù)停止的原因,修復(fù)缓艳,并把丟失的索引創(chuàng)建并修復(fù)數(shù)據(jù)
- 在異常日志打印那最好加入流控【用Guava.RateLimiter控制】
小結(jié)
jvm old區(qū)占用過(guò)高排查思路
- top查看占用cpu高的進(jìn)程
- jstat -gcutil pid 時(shí)間間隔 查看gc狀況
- jmap -dump:live,format=b,file=name.dump pid 導(dǎo)出dump文件
- 用visualVM分析dump文件
cpu占用過(guò)高排查思路
top 查看占用cpu的進(jìn)程 pid
top -Hp pid 查看進(jìn)程中占用cpu過(guò)高的線程id tid
printf '%x/n' tid 轉(zhuǎn)化為十六進(jìn)制
jstack pid |grep tid的十六進(jìn)制 -A 30 查看堆棧信息定位
歡迎關(guān)注公眾號(hào) 【每天曬白牙】校摩,獲取最新文章,我們一起交流阶淘,共同進(jìn)步衙吩!