事件回溯
1、7月26日上午11:34,告警郵件提示:tomcat內存使用率連續多次超過90%;
2、開發人員介入排查問題,11:40定位到存在oom問題,申請運維拉取線上tomcat 內存快照dump;
3、開發人員擔心服務抗不過下午的業務高峰期,讓運維在中午低谷期間重啟tomcat;
4、11:45,運維人員重啟tomcat,內存使用回落。
事件分析
1、根據監控歷史數據,發現7月10日后,內存逐步上升,且不能被full GC;懷疑和前一周版本有關,但檢查前一周版本內容,不可能導致omm;
2、拿到線上dump文件分析,發現drools規則引擎相關對象占據了90%的內存,初步斷定和drools的使用有關;
3、走讀代碼和drools的使用手冊,發現使用不當:在使用完drool的fact對象后,未能及時釋放,導致對象無法回收;
4、再回溯drools使用業務場景為當前app版本的新功能提供服務,新版本剛好在7月10日左右發布市場,所以,內存飆高最先出現在7月10日。
整個現象解釋通暢。
問題修復
1、在本地環境壓力測試模擬線上情況,重現oom;
2、更改drools相關使用代碼,加上資源釋放邏輯。
更改前:
{ ....... kSession.insert(fact); kSession.fireAllRules(); ....... }
更改后:
{
.......
FactHandle handle = kSession.insert(fact);
kSession.fireAllRules();
kSession.delete(handle);
........
}
3、更改后,再次壓測,問題修復。
總結
1、引入第三方jar時,核心功能一定要做壓力測試,模擬線上真實高並發場景,檢查是否存在並發問題或者omm問題;
2、使用第三方jar時,一定參考官方的資料或者demo做開發,切不可輕信網上隨意搜索得來的二手資料;
3、oom的現象:jvm內存使用不斷上升,且不能被full GC掉;正常情況下jvm內存使用曲線是平緩的鋸齒狀,而oom的內存使用曲線上升趨勢的鋸齒狀,如下:
線左邊為正常狀態,線右邊為oom時。
4、oom確認手段:jvm內存dump分析:
- 查看內存占用最大的對象,並據此找到泄露點;
- 間隔兩個full gc區間各拉一個dump,並比對這個時間段內增加的最多的對象,據此找到泄露點。(可能兩次full gc時間拉得較長,也可以退步到一個時間區間的對比)。