線上服務記憶體OOM問題定位三板斧
相信大家都有感觸,線上服務記憶體OOM的問題,是最難定位的問題,不過歸根結底,最常見的原因:
-
本身資源不夠
-
申請的太多
-
資源耗盡
58到家架構部,運維部,58速運技術部聯合進行了一次線上服務記憶體OOM問題排查實戰演練,將記憶體OOM問題定位三板斧分享出來,希望對大家也有幫助。
題目
某伺服器上部署了Java服務一枚,出現了OutOfMemoryError,請問有可能是什麼原因,問題應該如何定位?
不妨設服務程序PID為10765(沒錯,就是CPU佔用高的那個倒黴的程序《線上服務CPU100%問題快速定位實戰
解決思路
Java服務OOM,最常見的原因為:
-
有可能是記憶體分配確實過小,而正常業務使用了大量記憶體
-
某一個物件被頻繁申請,卻沒有釋放,記憶體不斷洩漏,導致記憶體耗盡
-
某一個資源被頻繁申請,系統資源耗盡,例如:不斷建立執行緒,不斷髮起網路連線
更具體的,可以使用以下的一些工具逐一排查。
一、確認是不是記憶體本身就分配過小
方法:jmap-heap 10765
如上圖,可以檢視新生代,老生代堆記憶體的分配大小以及使用情況,看是否本身分配過小。
二、找到最耗記憶體的物件
方法:jmap-histo:live 10765 | more
圖示:
如上圖,輸入命令後,會以表格的形式顯示存活物件的資訊,並按照所佔記憶體大小排序:
-
例項數
-
所佔記憶體大小
-
類名
是不是很直觀?對於例項數較多,佔用記憶體大小較多的例項/類,相關的程式碼就要針對性review了。
上圖中佔記憶體最多的物件是RingBufferLogEvent,共佔用記憶體18M,屬於正常使用範圍。
如果發現某類物件佔用記憶體很大(例如幾個G),很可能是類物件建立太多,且一直未釋放。例如:
-
申請完資源後,未呼叫close()或dispose()釋放資源
-
消費者消費速度慢(或停止消費了),而生產者不斷往佇列中投遞任務,導致佇列中任務累積過多
三、確認是否是資源耗盡
工具:
-
pstree
-
netstat
檢視程序建立的執行緒數,以及網路連線數,如果資源耗盡,也可能出現OOM。
這裡介紹另一種方法,通過
-
/proc/${PID}/fd
-
/proc/${PID}/task
可以分別檢視控制代碼詳情和執行緒數。
例如,某一臺線上伺服器的sshd程序PID是9339,檢視
-
ll /proc/9339/fd
-
ll /proc/9339/task
如上圖,sshd共佔用了四個控制代碼
-
0 ->標準輸入
-
1 ->標準輸出
-
2 ->標準錯誤輸出
-
3 -> socket(容易想到是監聽埠)
sshd只有一個主執行緒PID為9339,並沒有多執行緒。
所以,只要
-
ll /proc/${PID}/fd | wc -l
-
ll /proc/${PID}/task | wc -l(效果等同pstree -p | wc -l)
就能知道程序開啟的控制代碼數和執行緒數。
作業
對線上伺服器的一臺tomcat,檢視proc下的fd目錄和task目錄,特別是對於控制代碼fd目錄的查詢,有意想不到的驚喜喲,一定要動手試試哈。
如果有收穫,幫轉哈。
原文連結:
https://mp.weixin.qq.com/s?__biz=MjM5ODYxMDA5OQ==&mid=504476693&idx=1&sn=8eacd6c4f2f1b5c75bcb2dd9aa5a4b3e&chksm=3d2d01c90a5a88df9b455b3a2668eb2bc6caca4e0f8fd80de00f57553c75d14b44e271bc1f9d&mpshare=1&scene=1&srcid=0503JFddDj6OttjLZjPxU1Qj#rd
轉載於:https://my.oschina.net/anuodog/blog/1525025