一次生產OOM問題排查

現象分析:
我們有一個生產服務,規模是12臺機器*6個節點 = 72個節點的服務,最近老是出現某個節點突然掛掉的情況,問題出現頻繁,一天需要重啓很多個節點
查看tomcat日誌,發現是堆內存溢出
使用jmap -heap pid查看各個JVM內存空間的使用情況發現,所有的內存都被佔滿了,如下圖所示:
在這裏插入圖片描述
發現堆內存的確都被吃完了
使用top查看各個pid吃資源的情況後發現OOM的節點的CPU資源佔用特別高,基本都在100%以上
在這裏插入圖片描述
瘋狂吃CPU推斷應該是在JVM在進行fullGC(回收老年代,在進行fullGC的時候,程序不提供任何其他服務),使用jstat -gc pid查看GC情況
在這裏插入圖片描述
其中每個字段的意思對應如下

S0C:第一個倖存區的大小
S1C:第二個倖存區的大小
S0U:第一個倖存區的使用大小
S1U:第二個倖存區的使用大小
EC:伊甸園區的大小
EU:伊甸園區的使用大小
OC:老年代大小
OU:老年代使用大小
MC:方法區大小
MU:方法區使用大小
CCSC:壓縮類空間大小
CCSU:壓縮類空間使用大小
YGC:年輕代垃圾回收次數
YGCT:年輕代垃圾回收消耗時間
FGC:老年代垃圾回收次數
FGCT:老年代垃圾回收消耗時間
GCT:垃圾回收消耗總時間

看到其中fullGC的次數非常高,達到200-9000次,時間高達以小時計數,所以推斷應該是有大對象在內存中,並且一直在被引用

使用jmap -histo pid查看哪些對象佔用了空間發現char對象佔據了特別大的空間
在這裏插入圖片描述
在程序OOM的時候使用jmap -dump:live,format=b,file=tai.hprof pid這個命令dump下當時的內存文件到磁盤中。使用gzip壓縮文件(VPN限速太慢,時間可能很長)並且拉去到本機上

使用eclipse的插件分析dump文件tai.hprof

發現其中一個異常,一個線程對象持有了大量內存空間
在這裏插入圖片描述
點擊see stacktrace查看對應的堆棧信息
在這裏插入圖片描述
發現最後一步在程序中的堆棧信息是這一行代碼是最後執行代碼
在這裏插入圖片描述
查看內存佔用發現一個String對象使用內存非常多,並且結構有點像第三方返回對象
在這裏插入圖片描述
將值存儲到對應文件中發現這個字符串大小爲660MB,其中的值截取如下:
在這裏插入圖片描述
結果:結果是發現是調用下層的Go項目返回的HTTP response中返回的對象太大,經過各種裝換之後,一個線程持有的內存達到了4G多,而一個tomcat進程分配的內存總共也就5G,造成的OOM。經過排查Go項目。的確有一個地方有bug,存在笛卡爾積,在數據條數100+條列表的時候產生的對象會產生大對象的String返回到我們這個生產服務 。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章