一、背景介紹
最近在做日志服務的穩定性測試,大約跑一個小時左右一直報OOM,使用的測試java代碼結構跟NDIR穩定性測試使用的基本上是一致的,但是NDIR穩定性測試做過很多次了,沒有出現過類似問題,由于急著做穩定性測試,這個事情讓我很頭疼,于是花了一些時間去分析了一下內存情況。
二、問題分析
1.為什么NDIR可以使用,日志服務卻不可以?
我是這么分析的:
第一,我考慮了兩種穩定性測試請求情況的差別,主要是從并發線程數目、tps值以及交互的數據量出發,發現兩個測試框架的線程數目以及請求時實際的tps值大致是一個量級的,而交互的數據量差別很大,表現出來的情況是日志服務這邊打印的日志量過大,基本上是NDIR那邊10倍以上的日志量。
第二,我考慮了兩種穩定性測試配置上的差異,主要是從機器配置、mvn配置、jvm配置情況出發,發現這個方面是配置是一樣的,測試機器都是同一個。
第三,我考慮兩種穩定性測試代碼以及數據結構的差異,發現代碼結構以及使用的數據結構也都是差不多的,沒有發現什么特殊地方。
所以,可能導致日志服務出現問題的地方最有可能的地方就在交互數據量以及日志量,但是日志系統使用的是log4j,是一個很成熟的工具,應該沒有問題。
2.運行時大量消耗內存的到底是什么?
帶著上面的初步分析,我開始進行了內存排查這個使內存oom的對象到底是什么。
首先看看我mvn的配置貼出來:<argLine>-Dfile.encoding=UTF-8 -Xms512m -Xmx2048m -XX:PermSize=256m -XX:MaxPermSize=512M</argLine>
再看看實際運行時jvm情況:
實際機器分配的jvm參數與設置的一致,并且perm消耗值在不斷的長大。
再看看perm情況以及歷史上消耗內存情況:
從圖上可以看出消耗內存最多是是一個class [B的對象有4852個對象,如果能知道這個類是什么,那么就可以對癥下藥消滅它了。關鍵是這些jdk自帶的一些工具不直觀,看不出來是哪些類的對象,于是使用了更為直觀的大名鼎鼎的eclipse的插件MemoryAnalyzer來分析內存情況。
從這個圖中清晰看到基本上都是ByteArrayOutputStream這個類的對象將內存消耗盡了,那我們知道log4j寫日志以及maven打印console都是使用這個類的,于是打開去看看。
從這個圖中可以很清楚的看出,org.apache.maven.surefire.report.ReporterManager的consoleCapture方法消耗了其中的一半,也就是說console就占用了其中的一半內存,總共512M的term被這個console打印占去了260M,那剩下的肯定就不夠用了,而且這些byte[]是持久不釋放的,那么不管你有多少內存,只要運行時間夠長一定會將內存耗盡的。而這個時候去log4j的配置文件看一下發現:
那么情況就水落石出了,也能很好的解釋為什么同樣的穩定性測試框架NDIR能很好的運行日志服務就不可以,原因是NDIR那邊打印的日志量太小,三天到五天的穩定性測試不足以觸發perm的512M大小內存OOM的上限,如果繼續一直跑下去相信也是會發生OOM的情況的。花費了兩天和一個晚上的時間終于把問題解決了,這種成就感真的是比發薪水還要爽上N倍。
3.怎么解決?知道問題的原因后,解決問題就很簡單了。第一種方法,跑穩定性測試的時候去除console配置,這樣就不會有這種情況的發生。第二種辦法,大力的減少日志打印量,這樣可以跑的時間久很多,但是治標不治本。
三、總結
在我們實際的測試過程中可能會遇到很多的問題,這里總結為四點:
1.增強分析問題的能力。
2.增強掌握的知識和技能,學為所用。這是一個積累的過程,不要怕麻煩,慢慢積累知識和工具,試著去解決自己遇到的問題,感覺慢慢會有收貨。在這里解決這個問題帶來的那種感覺真的很棒。
3.我覺得遇到問題時,不要急于去做,留一些時間去思考也許結果會更好。在遇到這個問題的時候,因為是著急著上線,著急著做穩定性測試,所以就急忙著調試,各種嘗試以及去網上搜集資料,但始終沒有解決問題還花費掉一天一夜的時間,也沒有什么收貨,而第二天就靜下心來去分析問題,然后借助工具去排查問題,結果半天就解決了。
不定期發布有態度不忽悠的靠譜的文章,有內涵,有節操。
喜歡的朋友歡迎關注和轉發
本文章為作者原創
🈲禁止🈲
其他公眾賬號轉載,若有轉載,請標明出處
文章列表