內存溢出+CPU占用過高:問題排查+解決方案+復盤(超詳細分析教程)
原文地址
https://zhanghan.blog.csdn.net/article/details/109255980
前言
最近剛上線了一款社交項目,運行十多天后(運營持續每天推量),發現問題:
系統OOM(資源不能被釋放)導致服務器頻繁且長時間FGC導致服務器CPU持續飈高
日志中內存溢出:java.lang.OutOfMemoryError: Java heap space
程序十分卡頓,嚴重影響用戶使用
從以下方面,為大家分享此次問題解決流程
問題出現現象
臨時解決方案
復現問題
定位問題發生原因
優化代碼
優化后進行壓測,上線
復盤
學完本博文,你的收獲
排查內存溢出的思路
排查內存溢出過程中用到的命令及工具(Linux命令,Eclipse Memory Anaylzer[MAT])
定位系統內存溢出的代碼,並進行優化
此次內存溢出問題復盤
解決方案流程圖
問題&臨時解決方案&定位問題&最終解決方案
問題:
業務反饋程序用的十分卡,同時測試自己測的也十分卡
從ELK收集的請求日志發現確實存在問題,線上是兩台部署:兩台機器上都是,一次請求耗時由原來的幾毫秒變為10幾秒
CPU跑的過高,當時是4核,CPU持續飆到350%+;
當時一台服務器CPU截圖:
臨時解決方案
當時為了減少對業務影響,直接將生產兩台服務器上的項目進行重啟
項目啟動參數中沒有加內存溢出日志輸出(后續博客為大家介紹JVM調優時講解啟動命令中加內存溢出日志輸出),重啟后出問題時項目的JVM信息丟失了
復現問題方式:在開發環境對程序進行持續壓測;壓測相關服務器配置:
服務器配置:8核,16G
項目啟動內存:136M
Jmeter持續(循環)壓發消息接口10分鍾
定位問題
top命令查看最耗CPU的進程(進程:17038;CPU持續飆到595%+)
top -H pid號,查看該進程中最耗CPU的線程(發現有一些線程占用CPU較高)
將線程號轉為16進制,同時查看這些線程當前正在干什么(在此以17045線程為例)
可以看到最耗CPU的線程都是在進行GC
注意:
在FGC的時候會引起STW,所有應用都會短暫暫停,但是此時CPU仍然很忙,因為CPU在忙着進行FGC清理內存
用Jmap命令查看當前堆的使用情況(發現老年代現在已占用99.8%+)
查看gc 頻率的命令(其中O代表老年代占用率,FGC是FullGC次數,FGCT是fullGC時間;可以看出在頻繁FullGC但是老年代有資源一直釋放不掉)
通過分析出問題時線上日志發現內存溢出;至此定位到問題根源是內存溢出導致(有未釋放資源堆積,導致老年代被占滿,然后頻繁的FullGC但是資源一直釋放不了)
分析問題產生原因
由於線上當時直接重啟,未能保留當時的JVM內存文件;在開發環境進行循環壓測,復現線上問題,然后導出dump文件進行分析找到原因
生成dump文件命令
分析代碼
去代碼中全局搜這兩個類,發現只有在打日志的時候用到ClassClassPath類
分析ClassClassPath相關代碼:
用到ClassClassPath對象是一個靜態的ClassPool;
問題原因:classPath一直被靜態的全局pool所持有,導致GC一直釋放不掉;
優化代碼:每次用完ClassClassPath后將其釋放
每次對象使用完后從靜態pool中移除
注意:classPath=null這種方式是不能釋放掉的
優化后再次進行驗證
開發環境循環壓測,用MAT分析dump文件,發現內存中已不再堆積ClassClassPath類;優化前后接口吞吐量也提升8.2%
進行線上發布,觀察一周后,對內存分析發現正常
復盤:
項目比對:
為快速開發,社交的代碼從原來金融項目基礎上改造而來;
原來金融項目沒有內存溢出,而社交項目為什么內存溢出?
通過ELK統計一段時間的訪問量結果:
社交目前日訪問后台量65w+
金融項目只有4.5W+
社交和金融項目業務類型不一樣,所呈現出的特點也不同
去生產的金融項目中dump內存文件,用MAT工具分析,發現也存在ClassClassPath類堆積釋放不掉,只不過由於訪問量少,堆積量未占滿老年代而已;果斷在金融項目迭代時將其優化;
程序預警:為減少業務影響,增加接口耗時的預警(后續博文為大家共享);實現方式:
- 在每次程序處理完進行預警(比如本次請求>閾值);缺點:消耗性能影響正常業務
- 在ELK清洗時用相關插件進行預警;優點:和業務解耦,對業務無影響
服務器預警:運維增加CPU內存,日志內存溢出監控
總結
解決內存溢出過程總結:
不同的項目導致內存溢出原因是不同的;
重要的是排查思路
經過不斷的耐心的去觀察,測試,分析才能定位到問題並最終解決問題
在這次分析內存溢出過程中,我們也針對我們項目的JVM啟動參數進行了調優,在接下來的博文中為大家分享JVM調優
注意:
1,在FGC的時候會引起STW,所有應用都會短暫暫停,但是此時CPU仍然很忙,因為CPU在忙着進行FGC清理內存
2,使用jvisualvm來分析dump文件:
jvisualvm是JDK自帶的Java性能分析工具,在JDK的bin目錄下,文件名就叫jvisualvm.exe。
jvisualvm可以監控本地、遠程的java進程,實時查看進程的cpu、堆、線程等參數,對java進程生成dump文件,並對dump文件進行分析。
原文地址
https://zhanghan.blog.csdn.net/article/details/109255980