內存溢出+CPU占用過高:問題排查+解決方案+復盤(超詳細分析教程)


內存溢出+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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM