一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析

2022年10月30日00:38:35 科技 1434

背景介紹

系統運行在專有雲,應用運行時環境是EDAS Container( EDAS Container是EDAS 平台 HSF 應用運行的基礎容器,EDAS Container 包含 Ali-Tomcat 和 Pandora),消息處理使用的是【ons SDK】,消息消費者使用【PUSH】方式【批量】消費【普通消息】,MessageModel是【CLUSTERING】。
為了解決RocketMQ Producer某個性能問題,對Pandora進行了升級(主要是升級RocketMQ版本)。
下面從技術角度對升級中遇到的問題及分析過程進行總結,積累經驗以避免類似問題的發生。

問題描述

Pandora升級完成後,我們在RocketMQ控制台看到【消費者狀態】->【實時消息堆積量】有8億條,而每個Consumer實例堆積量是幾十條,如圖1:

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖1

在【消費者狀態】->【連接詳情】有消息消費失敗的情況,如圖2:

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖2

在應用伺服器ons.log也可以實時查看消息消費的指標信息,如圖3:

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖3

這部分的統計指標的實現可以查看:org.apache.rocketMQ.client.stat.ConsumerStatsManager

分析過程

根據我們前面幾篇關於MQ消息堆積的文章,可以知道:

  1. 消息堆積總量與Consumer實例消息堆積量相符的情況下,通常是Consumer消費能力弱導致堆積,詳情見:

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖4

為了便於理解,我們使用流程圖來表達下圖4中代碼主要邏輯,見圖5:

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖5

分析上面流程及代碼,發現ConsumeConcurrentlyContext類的ackIndex變數是分析消息成功與失敗的核心變數。

是否業務處理異常?

RocketMQ框架在業務處理類出現下面情況的時候,認為消息消費失敗:

  1. 業務處理類返回ConsumeConcurrentlyStatus.RECONSUME_LATER
  2. 業務處理類返回null
  3. 業務處理類拋出異常

通過業務處理類日誌可以確定業務沒有返回ConsumeConcurrentlyStatus.RECONSUME_LATER的情況;
從代碼可以看出,當出現2、3情況的時候,框架會將warn日誌列印到ons.log中,通過過濾ons.log中「consumeMessage exception」和「consumeMessage return null」關鍵詞,沒有相應的日誌記錄,所以也不是這兩種情況造成的。
備註:
當出現2、3情況的時候,ons.log日誌中並沒有列印出線程棧信息,如果想具體定位異常產生的位置,可以通過arthas stack命令進行分析。

arthas watch processConsumeResult

既然發送失敗消息到Broker重試隊列是在processConsumeResult方法調用的,那麼我們可以分析下該方法的入參及返回值情況。

watch com.alibaba.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService 
processConsumeResult "{params,returnObj}" "target.consumeGroup=='GID_CID_XXX'" -x 3 -n3

watch正常機器

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖6

watch異常機器

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖7

通過上面的watch,我們找到了問題最關鍵的地方,我們用下面的場景來分析下ackIndex不同值的影響。
場景一

  1. 業務處理類批量消費了【8】條數據,消費成功返回:CONSUME_SUCCESS
  2. ackIndex=Integer.MAX_VALUE
  3. RocketMQ框架分析消費成功了【8】條,失敗【0】條
  4. 因為都消費成功了,不會將消息發送到Broker重試隊列中

場景二

  1. 業務處理類批量消費了【8】條數據,消費成功返回:CONSUME_SUCCESS
  2. ackIndex=0
  3. RocketMQ框架分析消費成功了【1】條,失敗【7】條
  4. 因為有【7】條消費失敗,所以會將【7】條消費失敗的消息發送到Broker重試隊列中

arthas watch setAckIndex

既然有地方在修改ackIndex,先驗證下我們的判斷是否正確。

watch com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext setAckIndex "{params,returnObj}" "params[0]==0"

通過觀察,確實有地方在不斷將ackIndex的值修改為0。

arthas stack setAckIndex

我們繼續定位是什麼地方將ackIndex修改為0的。

stack com.alibaba.rocketmq.client.consumer.listener.ConsumeConcurrentlyContext setAckIndex "{params,returnObj}" "params[0]==0"

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖8

通過線程棧可知BatchConsumerImpl類調用了ConsumeConcurrentlyContext.setAckIndex方法。

arthas jad BatchConsumerImpl

沒有源碼的情況下,我們可以使用arthas jad對類進行反編譯。

jad com.aliyun.openservices.ons.api.impl.rocketmq.BatchConsumerImpl

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖9

ConsumeContext類實例欄位acknowledgeIndex默認值是多少呢?如果是0,問題的原因就找到了。

athas jad ConsumeContext

沒有源碼的情況下,我們可以使用arthas jad對類進行反編譯。

jad com.aliyun.openservices.ons.api.ConsumeContext

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖10

通過上面代碼可以看出,ConsumeContext類實例欄位acknowledgeIndex的默認值是0。

ProcessQueue

通過上面的分析,我們已經定位到了問題,ProcessQueue做下簡單描述,不做具體分析了。

一次RocketMQ ons SDK Bug導致消息不斷堆積到重試隊列的案例分析 - 天天要聞

圖11

解決辦法

由上面的分析,這個問題屬於RocketMQ ons SDK的一個Bug,修復就交給相應的產研團隊來fix吧。

經驗總結

1-5-10,1分鐘發現,5分鐘定位,10分鐘恢復。
當故障發生的時候,需要【1】最短時間內發現(監控報警是否做好),需要【10】最快的速度恢復(變更管理和預案是否做好),【5】似乎不是最主要的。

科技分類資訊推薦

萬元手機跑腿配送丟失引糾紛,律師:消費者可要求平台先行賠付 - 天天要聞

萬元手機跑腿配送丟失引糾紛,律師:消費者可要求平台先行賠付

近日,北京的師先生向新京報記者反映,今年5月底,他通過某外賣平台「跑腿一對一直送」服務,配送一部價值12400元的手機,此後卻遭遇手機丟失、配送員失聯、平台僅願賠付180元的維權難題。新京報記者查詢公開資料發現,類似的配送糾紛並非個例。在黑貓投訴平台上,同類的投訴多達數十起。京都律師事務所常莎律師表示,若配...
未按規定及時披露重大交易事項,龍辰科技被監管出具警示函 - 天天要聞

未按規定及時披露重大交易事項,龍辰科技被監管出具警示函

極目新聞記者 劉閃因未按規定及時披露重大交易事項,近日,湖北證監局對湖北龍辰科技股份有限公司、林美雲、林娜採取出具警示函措施。經查,2022年6月23日,湖北龍辰科技股份有限公司子公司安徽龍辰電子科技有限公司購買了一條BOPP電容薄膜生產線,交易價格為852萬歐元。公司未及時履行董事會審議程序,未及時進行信息披露,...
訂單激增致發貨延遲,泡泡瑪特公告致歉 - 天天要聞

訂單激增致發貨延遲,泡泡瑪特公告致歉

近日,在社交平台上有消費者表示,此前在泡泡瑪特官方渠道購買的潮玩產品,未能如訂單所顯示的最晚發貨時間進行發貨。在泡泡瑪特官方抽盒機小程序直播間中,亦有網友留言表示,希望直播間主播幫忙跟進延遲發貨等情況。直播間主播以直播間為售前部門為由,建議
小米汽車App顯示YU7訂車需等一年 雷軍:全力以赴抓緊生產 爭取早日交付 - 天天要聞

小米汽車App顯示YU7訂車需等一年 雷軍:全力以赴抓緊生產 爭取早日交付

快科技6月29消息,小米YU7恐怖的訂單量背後,是最長大約一年的提車等待時間。小米汽車App顯示了小米YU7三個版本的預估交付時間。其中,標準版最長,鎖定訂單後最快55-58周交付。Pro版最快49-52周。頂配小米YU7 Max最快,但也需要35-38周才能交付。那小米汽車APP上顯示的小米YU7預計交付時間,未來還有可能提前嗎?對此,小...
充電寶3C標識成熱門商品,電商平台仍有售賣 - 天天要聞

充電寶3C標識成熱門商品,電商平台仍有售賣

從6月28日起,按照民航局發布的通知,禁止旅客攜帶沒有3C標識、3C標識不清晰、被召回型號或批次的充電寶乘坐境內航班。記者發現,截至發稿時,仍有部分電商平台在售賣3C認證標籤貼紙等相關產品。首都國際機場和大興國際機場相關工作人員表示,自行張貼認證的充電寶不能帶上飛機。律師則表示,隨意張貼相關認證標識,可能會...
特朗普T1手機被曝由中國公司生產,官網撤下美國製造標籤 - 天天要聞

特朗普T1手機被曝由中國公司生產,官網撤下美國製造標籤

土豪金的外殼、星條旗標誌、開機就是「讓美國再次偉大」(MAGA)的壁紙,這款名為 T1 的智能手機設計上充滿了特朗普元素。特朗普資料圖 來源:新華社最近,特朗普集團高調進軍手機市場,推出一款售價499美元(將近3600元人民幣)的智能手機,宣稱這款手機由「美國製造」。特朗普的二兒子埃里克還對外宣稱,這款手機和移動服...
史上首次!特斯拉,大消息! - 天天要聞

史上首次!特斯拉,大消息!

6月28日,特斯拉完成了Model Y首次全自動駕駛交付。特斯拉CEO馬斯克在社交媒體上表示,「一輛汽車首次自動交付給主人」。根據他的描述,一輛特斯拉Model Y通過自動駕駛,從工廠到城市各處的客戶家中完成交付,並比計劃提前一天完成。他還讚揚了公司的軟體和AI晶元團隊。馬斯克強調,本次交付的Model Y的車內完全無人,也沒...
全無人駕駛!特斯拉實現史上首次車輛自己交付給車主 - 天天要聞

全無人駕駛!特斯拉實現史上首次車輛自己交付給車主

澎湃新聞 特斯拉又宣布了在自動駕駛運營上的新進展。6月28日,特斯拉官方微博發了一段視頻稱,一台Model Y從特斯拉得州超級工廠出發,全程30分鐘車程,最終平安來到客戶家門口把自己交付給新車主。全程沒有駕駛員、沒有遠程操控,最高時速達到1