天天看點

記一次JVM記憶體溢出排查過程

記憶體溢出排查

    • 1. 頻繁FullGC預警
    • 2. 排查原因

1. 頻繁FullGC預警

1.1 頻繁FullGC告警:

時間發生在2020-07-10(周五)晚上21:15分左右,本該收拾行囊下班,突然收到頻繁FullGC預警消息,吓的菊花一緊,過一會收到接口探活告警,說明服務已經不可用了;

1.2 下線目前問題節點:

服務是3台節點部署,既然其中一台出現問題,在上層網關上将目前節點下線,保證使用者的請求不會再打到目前節點;

1.3 年青代和老年代情況:

登入監控平台檢視jvm的情況:

記一次JVM記憶體溢出排查過程

黃色線:老年代

藍色線:年青化

在21:10左右時,就已經開始發生明顯的頻繁FullGC;

1.4 YGC次數和FGC次數:

登入監控平台檢視jvm的情況:

記一次JVM記憶體溢出排查過程
藍色:目前出問題節點的YGC總次數;
記一次JVM記憶體溢出排查過程
藍色:目前出問題節點的FGC總次數;

1.4 年青代具體情況:

記一次JVM記憶體溢出排查過程

黃色:S0;

紫色:S1;

藍色:Eden;

大概在21:10 - 21: 20這段時間一直在YGC

2. 排查原因

經過上面的分析,和上次遇到的頻繁FGC問題不一樣 上次的是突增,突然被記憶體被占滿,而本次的是存在緩慢的增長過程,猜測程式可能做了大批量導出;

2.1 生成dump檔案

檢視是否生成dump檔案,如果沒有生成,手動通過: jmap -dump:live,format=b,file=dump.hprof 程序号;生成dump檔案;

2.2 重新開機服務

既然記憶體快照儲存下來了,就可以放心的重新啟動服務;

2.3 檢視背景記錄檔

檢視背景記錄檔,發現使用者對一張擁有2200W記錄的表做了一次導出,但是導出的sql裡面有id值,按道理說隻會導出一條;也不會導緻程式記憶體溢出啊;

2.4 分析dump檔案

既然可疑的導出有明确指定id,不會造成大批量的資料被加載進服務,那隻能分析dump檔案

dump檔案大約28G,分析套路和 記一次排查線上頻繁FullGC 過程 一樣;

最後分析出來三個zip檔案,解析後檢視index.html;

記一次JVM記憶體溢出排查過程
大概占了24.3G,檢視詳細的調用棧;
記一次JVM記憶體溢出排查過程
還是出在導出的問題上;

2.5 檢視伺服器日志

經過精心排查伺服器日志發現,在使用者跳轉到查詢清單時,在沒有輸入任何查詢條件的情況下,點選過導出按鈕,造成大量記錄被加載進記憶體;

2.6 服務優化

1.導出的限制方面做控制;

2.大資料量導出考慮資料遷移到其它平台;

3.為什麼全量導出的操作沒有被記錄到記錄檔(待排查)

4.網關高耗時請求也考慮告警;