您好,這里是「碼農(nóng)鏢局」CSDN博客,歡迎您來(lái),歡迎您再來(lái)~
除了Tomcat、Jetty,另一個(gè)常見(jiàn)的可能出現(xiàn)OOM的地方就是微服務(wù)架構(gòu)下的一次RPC調(diào)用過(guò)程中。筆者曾經(jīng)經(jīng)歷過(guò)的一次OOM就是基于Thrift框架封裝出來(lái)的一個(gè)RPC框架導(dǎo)致的宕機(jī)。
?
也就是當(dāng)服務(wù)A更新后,服務(wù)B宕機(jī)了。
通過(guò)查看GC日志,發(fā)現(xiàn)是JVM堆拋出的OOM。打開(kāi)內(nèi)存快照,發(fā)現(xiàn)超大byte[]數(shù)組,而這個(gè)超大的byte[]數(shù)組是由RPC框架持有的。
?
初步判定原因是:服務(wù)A修改了Request類,但服務(wù)B未更新該類,還是舊版本,因此導(dǎo)致反序列化失敗時(shí)RPC會(huì)開(kāi)辟一個(gè)byte[]數(shù)組,默認(rèn)大小是4G。
?
因此最終的解決方案也很簡(jiǎn)單:
1、服務(wù)B更新Request類;
2、將RPC默認(rèn)byte[]數(shù)組大小調(diào)整為4M。
另一次事故是由馬虎的開(kāi)發(fā)工程師引起的。某個(gè)馬虎的工程師用mybatis寫的SQL語(yǔ)句在某些情況下允許不加where條件就可以執(zhí)行,這導(dǎo)致一下子查出來(lái)上百萬(wàn)條數(shù)據(jù),引發(fā)系統(tǒng)OOM。這種情況下,MAT工具對(duì)由Web容器(Tomcat/Jetty)或者RPC等底層框架所引發(fā)的OOM故障,用處并不大。但如果OOM主要是由于業(yè)務(wù)代碼導(dǎo)致,那使用起來(lái)就簡(jiǎn)單得多。使用MAT工具定位問(wèn)題的時(shí)候:
1、利用histogram功能占用內(nèi)存最多的對(duì)象
2、找到占用內(nèi)存過(guò)多的對(duì)象,并深入看看對(duì)象之間的持有關(guān)系
3、找到問(wèn)題代碼
與前面的RPC引發(fā)的OOM類似,有一個(gè)線上數(shù)據(jù)同步系統(tǒng),專門從另一個(gè)系統(tǒng)同步數(shù)據(jù),通過(guò)kafka來(lái)發(fā)送與消費(fèi)數(shù)據(jù)。即使是這么簡(jiǎn)單的一個(gè)系統(tǒng),也會(huì)不時(shí)地報(bào)一個(gè)OOM錯(cuò)誤,且頻率越來(lái)越高。這難道又是工程師的粗心引起的嗎?
?
通過(guò)簡(jiǎn)單分析可以知道,既然每次重啟過(guò)后都會(huì)頻繁出現(xiàn)OOM,就說(shuō)明內(nèi)存使用率會(huì)不斷上漲且難以清理。而JVM出現(xiàn)OOM,一般都是由兩種情況引起:
1、要么高并發(fā)高負(fù)載,一瞬間創(chuàng)建太多對(duì)象,導(dǎo)致內(nèi)存放不下
2、要么存活對(duì)象太多,GC無(wú)法回收
而針對(duì)此案例,極有可能就是第二種情況:存活對(duì)象太多。
?
這一點(diǎn)可以通過(guò)jstat來(lái)驗(yàn)證。重啟系統(tǒng)后,啟動(dòng)jstat,觀察到:
1、老年代持續(xù)增長(zhǎng),且老年代使用率達(dá)到100%后,F(xiàn)ull GC根本回收不掉任何對(duì)象
2、老年代維持一段時(shí)間的100%使用率后,發(fā)生OOM
同時(shí)通過(guò)MAT找到占用內(nèi)存最多的對(duì)象。利用Histogram功能,最終發(fā)現(xiàn)問(wèn)題原因:
1、kafka的吞吐量和數(shù)據(jù)庫(kù)的吞吐量完全不是一個(gè)數(shù)量級(jí);
2、數(shù)據(jù)庫(kù)的處理能力慢,導(dǎo)致數(shù)據(jù)不斷積壓,最終內(nèi)存溢出;
3、典型的沒(méi)控制好生產(chǎn)與消費(fèi)數(shù)據(jù)的速率導(dǎo)致的OOM。
?
最后總結(jié)一下這幾個(gè)案例:
1、必須對(duì)線上系統(tǒng)使用的各種技術(shù),從服務(wù)器框架,到第三方框架,到Tomcat/Jetty等Web服務(wù)器,再到各種底層的中間件系統(tǒng),都有深入的理解;
2、一般線上系統(tǒng)的故障,極少數(shù)是由業(yè)務(wù)代碼直接導(dǎo)致的——更一般的情況是某個(gè)開(kāi)源技術(shù)的內(nèi)核代碼就可能存在一定的故障和缺陷,只是在某些極端場(chǎng)景下才被發(fā)現(xiàn)而已;
3、定位、解決OOM問(wèn)題,需要仔細(xì)研究底層源碼,再結(jié)合線上業(yè)務(wù)、系統(tǒng)負(fù)載、參數(shù)配置和系統(tǒng)日志(含GC日志)等多種手段,才能完成;
4、一般情況下禁止顯式調(diào)用System.gc(),但是如果開(kāi)發(fā)的是文件存儲(chǔ)、IM等大量使用NIO技術(shù)的應(yīng)用,就不要禁止System.gc(),但業(yè)務(wù)代碼還是不要出現(xiàn)System.gc();
5、生產(chǎn)環(huán)境一不使用parallel垃圾回收器;
6、一個(gè)Tomcat就是一個(gè)進(jìn)程,不管在上面部署了多少個(gè)應(yīng)用,都只有一個(gè)JVM進(jìn)程。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-614041.html
感謝您的大駕光臨!歡迎騷擾,不勝榮幸~文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-614041.html
到了這里,關(guān)于JVM系統(tǒng)優(yōu)化實(shí)踐(22):GC生產(chǎn)環(huán)境案例(五)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!