1. 程式人生 > 實用技巧 >線上服務記憶體OOM問題定位三板斧

線上服務記憶體OOM問題定位三板斧

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

相信大家都有感觸,線上服務記憶體OOM的問題,是最難定位的問題,不過歸根結底,最常見的原因:

  • 本身資源不夠

  • 申請的太多

  • 資源耗盡

58到家架構部,運維部,58速運技術部聯合進行了一次線上服務記憶體OOM問題排查實戰演練,將記憶體OOM問題定位三板斧分享出來,希望對大家也有幫助。

題目

某伺服器上部署了Java服務一枚,出現了OutOfMemoryError,請問有可能是什麼原因,問題應該如何定位?

不妨設服務程序PID為10765(沒錯,就是CPU佔用高的那個倒黴的程序《線上服務CPU100%問題快速定位實戰

》)。

解決思路

Java服務OOM,最常見的原因為:

  • 有可能是記憶體分配確實過小,而正常業務使用了大量記憶體

  • 某一個物件被頻繁申請,卻沒有釋放,記憶體不斷洩漏,導致記憶體耗盡

  • 某一個資源被頻繁申請,系統資源耗盡,例如:不斷建立執行緒,不斷髮起網路連線

更具體的,可以使用以下的一些工具逐一排查。

一、確認是不是記憶體本身就分配過小

方法:jmap-heap 10765

03135920_uglm.jpg

如上圖,可以檢視新生代,老生代堆記憶體的分配大小以及使用情況,看是否本身分配過小。

二、找到最耗記憶體的物件

方法:jmap-histo:live 10765 | more

圖示

03135920_X6LU.jpg

如上圖,輸入命令後,會以表格的形式顯示存活物件的資訊,並按照所佔記憶體大小排序:

  • 例項數

  • 所佔記憶體大小

  • 類名

是不是很直觀?對於例項數較多,佔用記憶體大小較多的例項/類,相關的程式碼就要針對性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

03135920_J7d0.jpg

如上圖,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