天天看點

記一次stormOOM異常的産生與解決

最近這段時間開始了一個新項目,項目使用rabbitMQ存儲采集資料,通過storm對rabbitMQ中的資料進行實時計算,将結果存入到rabbitMQ的另一個隊列中,再由另外一個storm服務将結果儲存到elasticsearch中進行存儲,以此實作大資料的實時計算存儲。

在項目首次部署階段,一切正常。在storm服務部署完成并啟動後,開啟采集服務,成功實作了資料的實時計算與存儲。設定的單批次最大消費數為10000,rabbit的incoming與diliver為400-500/s。運作結果一切正常,沒有出現資料丢失或資料積壓的情況。

然而好景不長,沒過幾天後的一次更新,将storm服務kill掉重新開機後,rabbit的資料在重新開機過程中有了一定量的堆積,此時重新開機storm後出現了OOM異常。

記一次stormOOM異常的産生與解決
WHAT???為啥之前本地測試積壓了十幾萬條資料,每秒1000-1200條資料都能成功消費,而生産不過每秒400-500條的資料卻出現了OOM記憶體不足的情況呢?
記一次stormOOM異常的産生與解決

錯誤複現

首先在本地模拟資料,模拟資料總計20000條,存入rabbitMQ中。

記一次stormOOM異常的産生與解決

為了測試資料堆積場景下的資料消費情況,分别開啟Storm服務,對rabbit資料進行計算與存儲。

第一階段:資料的實時計算

記一次stormOOM異常的産生與解決

第二階段:資料的存儲

記一次stormOOM異常的産生與解決

可以看到storm的資料是能夠成功計算與存儲的。即使出現積壓也沒有出現資料丢失或OOM異常。

此刻,模拟資料總計條數不變,将每條消息的大小擴大為以前的10倍左右

原資料大小:

記一次stormOOM異常的産生與解決

修改後的資料大小:

記一次stormOOM異常的産生與解決

重新開啟storm服務

第一階段:

記一次stormOOM異常的産生與解決
記一次stormOOM異常的産生與解決

第二階段:

記一次stormOOM異常的産生與解決

可以看到資料出現了很明顯的丢失情況,背景日志也列印出了OOM異常

記一次stormOOM異常的産生與解決

問題分析

Storm對每個Topology預設的大小配置設定是768M,在生産環境,資料通過analyse服務時沒超過這個記憶體門檻值,是以當時analyse服務在生産沒有出現OOM異常,而通過計算處理後放入另外一個隊列中的資料,單批次資料的大小超過了記憶體大小門檻值,是以在save服務出現了OOM異常。

在測試條件下,saveTopology的記憶體占用就已經超過了768M,是以在analyse服務下也出現了OOM異常,

到了Save服務下甚至隻有600條不到資料成功寫入ES。

問題解決

在項目中,添加配置

worker.heap.memory.mb

topology.worker.max.heap.size.mb

配置從Zookeeper中讀取,不同的環境下配置不同的記憶體大小。

記一次stormOOM異常的産生與解決
記一次stormOOM異常的産生與解決

Assigned Mem(MB) 為配置的記憶體大小(預設條件下是768M)+LogWriter的64M

記一次stormOOM異常的産生與解決

此時再重新進行資料模拟及積壓資料的計算與存儲

第一階段

記一次stormOOM異常的産生與解決

第二階段

記一次stormOOM異常的産生與解決

可以看到這次不再出現OOM異常,資料成功進行了計算與存儲。

總結

在一般流式計算的場景下,資料進入隊列立刻被消費時,很多問題不會出現。但這并不代表系統就是沒有問題的。在某個時間點,突然有大批量的資料寫入,或當Storm服務中斷掉等一系列場景使得消息隊列中有大量資料積壓時,記憶體、線程、隊列等一系列因素會導緻很多在開發時沒有注意的細節問題,如何保證資料能加速消費的同時不出現資料的丢失,也是一個需要開發者思考的問題。