問題排查|為啥RocketMQ廣播消費每次啟動都會從頭開始消費?

張哥說技術發表於2022-12-19

1、現象

最近聽到有專案反饋,使用公司內部封裝的訊息sdk,在使用RocketMQ廣播消費時,每一次版本釋出,消費者重啟後,都會從最早位點開始消費,造成嚴重的訊息消費積壓,不僅對訊息服務的負載產生極大影響,也會讓發版本後訊息出來不及時。

那這是什麼原因引起的呢?

2、問題排查

熟悉RocketMQ的小夥伴應該知道,消費組在重啟時優先會去查詢上一次的消費位點,只要能查詢到有效的位點,則會從查詢到的位點開始消費,如果查詢不到有效位點,則按照消費組設定的ConsumeFromWhere策略去查詢位點,其可選值:

  • CONSUME_FROM_FIRST_OFFSET 從最早位點開始消費

  • CONSUME_FROM_LAST_OFFSET

    從最新位點開始消費

  • CONSUME_FROM_TIMESTAMP 從指定時間開始消費

現在的現象是從最早消費,基本可以認為是消費者在啟動時並沒有查詢到有效位點,但RocketMQ廣播消費一樣會儲存消費進度,只是儲存在消費端本地,那為什麼會讀取不到消費進度檔案呢?

注意:如果在容器環境中使用RocketMQ的廣播消費,進度檔案不能儲存在容器本身,應該需要引用外部儲存檔案,即容器建立後,可以統一訪問該共享目錄,否則肯定會出現本文出現的問題。

為了破解該問題,首先我們要知道RocketMQ廣播消費消費進度檔案的儲存目錄,由於本文遇到的環境是虛擬機器環境,結合RocketMQ廣播消費的核心實現類LocalFileOffsetStore中如下程式碼:

問題排查|為啥RocketMQ廣播消費每次啟動都會從頭開始消費?

結合上述兩段核心程式碼,我們可以得知RocketMQ廣播消費模式,訊息消費進度檔案的儲存根目錄為 /{使用者主目錄}/.rocketmq_offsets,子目錄為/mqClientId/{consumerGroupName}/offsets.json。其中mqClient為消費者clientId,consumerGroupName為消費最名稱。

於是立馬登入伺服器,進入到.rocketmq_offsets資料夾,看到下面存在很多子資料夾,如下圖所示:

問題排查|為啥RocketMQ廣播消費每次啟動都會從頭開始消費?

不進引起了我的注意,按照上述的定義,一個消費者一個客戶端擁有自己的專屬資料夾,從這裡看,顯然是消費組在啟動時就會建立一個新的資料夾,故載入不到之前儲存的消費進度資訊,綜合來看,問題就出在mqClientId上,也就是這個mqClinetId並不唯一,每一次啟動時會變化,最終檢視內部程式碼,發現消費組在構建mqClientID時確實存在問題,因為會取當前時間戳,程式碼如下:

問題排查|為啥RocketMQ廣播消費每次啟動都會從頭開始消費?

破案了。那原生使用RocketMQ的廣播消費,是否會存在同樣的問題呢?答案是不會,因為clientId的預設生成規則如下所示:

問題排查|為啥RocketMQ廣播消費每次啟動都會從頭開始消費?

也就是預設的mqClientId是IP地址 +  @ DEFAULT,這個無論啟動多少次,也不會變化。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024923/viewspace-2928612/,如需轉載,請註明出處,否則將追究法律責任。

相關文章