最近這段時間開始了一個新項目,項目使用rabbitMQ存儲采集資料,通過storm對rabbitMQ中的資料進行實時計算,将結果存入到rabbitMQ的另一個隊列中,再由另外一個storm服務将結果儲存到elasticsearch中進行存儲,以此實作大資料的實時計算存儲。
在項目首次部署階段,一切正常。在storm服務部署完成并啟動後,開啟采集服務,成功實作了資料的實時計算與存儲。設定的單批次最大消費數為10000,rabbit的incoming與diliver為400-500/s。運作結果一切正常,沒有出現資料丢失或資料積壓的情況。
然而好景不長,沒過幾天後的一次更新,将storm服務kill掉重新開機後,rabbit的資料在重新開機過程中有了一定量的堆積,此時重新開機storm後出現了OOM異常。

錯誤複現
首先在本地模拟資料,模拟資料總計20000條,存入rabbitMQ中。
為了測試資料堆積場景下的資料消費情況,分别開啟Storm服務,對rabbit資料進行計算與存儲。
第一階段:資料的實時計算
第二階段:資料的存儲
可以看到storm的資料是能夠成功計算與存儲的。即使出現積壓也沒有出現資料丢失或OOM異常。
此刻,模拟資料總計條數不變,将每條消息的大小擴大為以前的10倍左右
原資料大小:
修改後的資料大小:
重新開啟storm服務
第一階段:
第二階段:
可以看到資料出現了很明顯的丢失情況,背景日志也列印出了OOM異常
問題分析
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中讀取,不同的環境下配置不同的記憶體大小。
Assigned Mem(MB) 為配置的記憶體大小(預設條件下是768M)+LogWriter的64M
此時再重新進行資料模拟及積壓資料的計算與存儲
第一階段
第二階段
可以看到這次不再出現OOM異常,資料成功進行了計算與存儲。
總結
在一般流式計算的場景下,資料進入隊列立刻被消費時,很多問題不會出現。但這并不代表系統就是沒有問題的。在某個時間點,突然有大批量的資料寫入,或當Storm服務中斷掉等一系列場景使得消息隊列中有大量資料積壓時,記憶體、線程、隊列等一系列因素會導緻很多在開發時沒有注意的細節問題,如何保證資料能加速消費的同時不出現資料的丢失,也是一個需要開發者思考的問題。