每天資訊上傳圖片OOM了,該怎麼辦

菜單

上傳圖片OOM了,該怎麼辦

測試同學在管理後臺上傳一張3M的圖片時,發現介面停留在卡死的狀態,就喊我排查下。聽到這個後首先要做的就是看這個管理後臺服務的日誌。

上傳圖片OOM了,該怎麼辦

從日誌裡清楚地看到,居然是可惡的堆記憶體溢位。

堆記憶體溢位的排查過程

還好我們jvm的啟動引數裡有配置在發生OOM時dump記憶體快照

-XX:+HeapDumpOnOutOfMemoryError

-XX:HeapDumpPath=/app/sc-manage/logs

我登入到OOM的這臺機器把記憶體快照檔案下載到本地,準備用MAT來分析下。

MAT是什麼

MAT是一款強大的記憶體分析工具,如果你的開發工具是Eclipse,可以直接整合MAT外掛來使用,很多人其實開發是用IntelliJ IDEA的,所以這個時候可以直接下載一個MAT來使用即可,官網有下載地址可以百度。

大家選擇自己的膝上型電腦的作業系統對應的版本就可以了,他是支援Windows、Mac、Linux三種作業系統的。

下載好MAT後,在他的安裝目錄裡,可以看到一個檔名字叫做:MemoryAnalyzer。ini

這個檔案裡的內容類似如下所示:

上傳圖片OOM了,該怎麼辦

如果dump出來的記憶體快照很大,比如有幾個G,你務必在啟動MAT之前,先在這個配置檔案裡給MAT本身設定一下堆記憶體大小,比如設定為4個G,或者8個G,他這裡預設-Xmx1024m是1G。接著大家直接啟動MAT即可,啟動之後看到的介面中有一個選型是:Open a Heap Dump,就是開啟一個記憶體快照的意思,選擇他,然後選擇本地的一個記憶體快照檔案即可。

下面是我開啟檔案後看到的截圖

上傳圖片OOM了,該怎麼辦

上傳圖片OOM了,該怎麼辦

上傳圖片OOM了,該怎麼辦

從這裡可以看到主要是這兩個200多M的大物件,但是這裡看不出是程式碼哪裡建立的這些大物件的,我們點選stackTrace找到有問題的業務程式碼

上傳圖片OOM了,該怎麼辦

就是我們自己封裝的上床圖片元件有問題,將進度條拖到右邊找到出問題的程式碼在哪一行

上傳圖片OOM了,該怎麼辦

然後開啟程式碼找到是這一行程式碼導致的

上傳圖片OOM了,該怎麼辦

這一行程式碼是用的開源工具主要用來壓縮圖片的,上面分析的大物件就是這個壓縮工具核心程式碼裡生成的。

解決辦法

我看了下我們JVM的啟動引數配置,如下所示

上傳圖片OOM了,該怎麼辦

堆記憶體設定非常不合理,年輕代256M老年代是768M,然後eden和survivor區的比例是8:1:1,這就導致每個S區大小隻有25M左右,導致壓縮時大物件在S區放不下直接進入老年代,老年代也裝不下了觸發Full gc又不能回收掉就導致OOM了,公司目前的堆記憶體分配如下

上傳圖片OOM了,該怎麼辦

在瞭解到公司機器配置是8核32G的,雖然部署了十幾個服務,每個服務的JVM引數都是用的同一套模板,機器剩餘還有18G記憶體,我這邊修改了管理後臺服務JVM啟動引數重啟了例項,修改後的JVM引數如下

上傳圖片OOM了,該怎麼辦

修改後的堆記憶體配置如下

修改後的堆記憶體配置如下

上傳圖片OOM了,該怎麼辦

目的是讓壓縮產生的200M大物件比S區的50%還要小,不會觸發動態年齡判斷機制等直接進入老年代,讓這些物件在young gc裡就能回收掉不要進入老年代。重啟例項後再管理後臺上傳大圖片時,用jstat看了下gc情況,基本達到預期了。

上傳圖片OOM了,該怎麼辦

寫在後面

壓縮圖片一般業內用的比較多是ImageMagic,我們系統是前人留下的一個工具,從結果來看壓縮時這麼耗費記憶體,並不是那麼好用,後續考慮切換到ImageMagic,現在先暫時擴大JVM的堆記憶體來解決。