去年寫過一篇《Topic數量太多!RocketMQ炸了!》,大家評價還不錯。
結果,2024年的開頭,我們的RocketMQ又炸了!
1、問題現象
先說明下RocketMQ版本, 4.6.0的老版本了。
線下環境客戶端啓動會頻繁報錯響應超時,導致consumer
實例化失敗,無法啓動應用。
2、排查
確認線下環境RocketMQ集羣流量、生產消費數量無異常。
集羣gc次數不多,但是耗時高。(原本監控看板異常數據缺失,所以少了前面一段)
master節點cpu使用率、load極高。
升配,4c8g升級8c32g,擴大jvm內存。
系統指標略有下降,但是客戶端異常沒有明顯改善。
只能進一步排查根因,還得上arthas
。
thread -n 3
查看cpu高的線程在做什麼。
發現兩個異常線程。
1)一個線程在執行AdminBrokerProcessor.queryTopicConsumerByWho()
。
這個是查詢Topic
的conusmerGroup
信息。
比較奇怪的是,這個請求很頻繁,後來發現是控制檯應用dashboard有個定時任務,30s查詢一次。
這個請求的耗時主要是在數組的遍歷處理上,說明內存中的數據非常大。
而這個源碼中的offsetTable
,就是RocketMQ中保存consumerGroup
位點信息的對象。它的key
是topic@group
拼接的。
先臨時處理,把dashboard應用關閉了,減少請求。但是效果並不明顯。
2)另一個線程在執行定時任務ConsumerOffsetManager.persist()
。
(線程調用信息忘記截圖了)
這個是RocketMQ集羣持久化consumerGroup
的offset
信息的定時任務。
會將整個內存對象轉化爲jsonString
寫入磁盤文件中。
這個內存對象就是前面提到的offsetTable
,就是RocketMQ中保存consumerGroup
位點信息的對象。
這裏消耗資源多,還是說明我們的內存對象非常大。
因爲是線下環境,可靠性要求不高。所以先臨時處理,把定時任務默認配置5s改成50s,減少持久化次數。
效果顯著,機器cpu、負載都明顯改善。
好了,現在問題的矛頭都指向了這個offsetTable,那它到底有多大,爲什麼這麼大?
3、定位根因
3.1 直接原因
大對象的定位,一般來說需要dump看看,不過這個對象有點特殊,剛剛也提到了它會被持久化到文件中,所以直接看文件大小和內容就行了。
持久化文件的配置路徑,可以看下啓動的conf.properties
storePathRootDir=/usr/local/rocketmq/store1
storePathCommitLog=/usr/local/rocketmq/store1/commitlog
storePathConsumerQueue=/usr/local/rocketmq/store1/consumequeue
storePathIndex=/usr/local/rocketmq/store1/index
在/usr/local/rocketmq/store1
目錄下找到config
文件夾的consummerOffset.json
文件,44M,amazing~
對一個幾十M的對象頻繁序列化和持久化,加上內網磁盤比較差,難怪負載如此高。
(這裏截圖是當時應急時備份的文件,新的文件目前是414K)
3.2 根本原因
爲什麼這個內存對象這麼大呢?
查看了下文件內容,是RocketMQ中保存consumerGroup
位點信息的對象,它的key
是topic@group
拼接的。
我們發現大量奇怪的consumerGroup name
,跟一個topic
聯合產生了幾千個key
。
查看了下內部封裝的客戶端代碼,找到了罪魁禍首。
線下環境會根據小環境(比如自己起的測試、單測環境、CI測試環境等)拼接一個獨立的consumerGroup name
。
在線下,每次CI的測試環境名字會變化,所以導致consumerGroup name
數量急劇膨脹。
4、優化
問題找到了,直接的解決方式是刪除文件中無用的consumerGroup name
,重啓broker
進行加載。
由於是線下環境,不需要擔心位點丟失的問題,同時當客戶端請求時會自動創建新的位點信息,所以可以考慮直接刪除。
先停止broker
進程(否則會自動落盤內存數據,創建新的文件),然後重命名相關文件(用於備份回滾),重新啓動broker
進程,讀取空文件加載空對象。
重啓後,各個客戶端在請求集羣時,會自動創建訂閱關係和消費位點記錄,負載略有升高,然後就恢復到較低的負載水位了。
24h的監控顯示,優化效果顯著,整個機器負載降低,請求讀寫耗時也顯著降低。
注意:
保存訂閱關係的subscriptionGroup.json也存在同樣consumerGroup過多導致膨脹的問題,同樣的原因和優化方式。默認訂閱關係也是會自動創建的。
這裏就不展開贅述了。
5、擴展一下
如果類似的問題出在線上怎麼辦?
事後來看,類似問題是能夠提前避免的,主要考慮兩個措施:
要做好持久化文件(對應內存對象)大小監控,避免出現內存大對象。如果發現異常增長,必須提前排查處理。
磁盤要足夠好,使用SSD是基本要求,避免頻繁刷盤導致負載升高。
往期熱門筆記合集推薦:
原創:阿丸筆記(微信公衆號:aone_note),歡迎 分享,轉載請保留出處。
沒有留言功能的悲傷,掃描下方二維碼「加我」聊些有的沒的吧~
本文分享自微信公衆號 - 阿丸筆記(aone_note)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。