天天看點

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

上一章: 發送問題排查 | 《Rocket MQ 使用排查指南》第二章>>> 下一章: 其他問題排查 | 《Rocket MQ 使用排查指南》第四章>>>

點選免費下載下傳

《Rocket MQ 使用排查指南》>>>

消費問題排查 | 《Rocket MQ 使用排查指南》第三章
也可以PC端點選 https://developer.aliyun.com/topic/download?id=820 下載下傳

消費問題排查

堆積負載問題常見問題

Java 程序消息堆積嚴重

【問題描述】:

消費者狀态頁面,Group ID 的實時消息堆積量的值高于預期,且性能明顯下降。

【排查步驟】:

  1. 在消息隊列 MQ 控制台 , 通過檢視消費者狀态擷取消息堆積的消費者執行個體所對應的主控端 IP,并登入該主控端或容器。
  2. 執行以下任一指令檢視程序 pid:
- ps -ef |grep java
 - jps -lm
           
  1. 執行以下指令檢視堆棧資訊:
- jstack -l pid > /tmp/pid.jstack
           
  1. 執行以下指令檢視 ConsumeMessageThread 的資訊,重點關注線程的狀态及堆棧:
cat /tmp/pid.jstack|grep ConsumeMessageThread -A 10 –color           

隻需要注意兩種狀态就可以。

  • BLOCKED 此狀态說明消費者線程被阻塞了,導緻消息的消費被停滞了,進而導緻消息堆積的産生。這時要通過上面的堆棧資訊來檢視具體是阻塞在那個接口。
  • WAITING 這個狀态要分兩種情況來說明:
消費問題排查 | 《Rocket MQ 使用排查指南》第三章

(1)如果是上圖所顯示的堆棧資訊,說明消費者線程在等待消息消費,此為正常狀态。

(2)如果不是上圖所顯示的堆棧資訊,可以重複上面的 3、4 兩步,檢查這個這個消費者線程是否一直處于這種狀态,而且堆棧資訊顯示也是一樣的。這個現象說明在消費邏輯的代碼中,由于某種資源緊張,導緻擷取這種資源的時間較長,進而導緻消息消費的耗時增長,TPS 下降,消息消費的速度跟不上消息生産的速度,進而導緻消息堆積。

為什麼消費者堆積負載不均

每個消費者堆積數量差異很大,負載非常不均,具展現象如圖

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

【問題原因】:

這個是配置設定政策,當所有消費執行個體都達到消費能力上限後,不再完全配置設定到所有都隊列,會集中配置設定到前面的隊列。這種現象一般建議提升代碼消費能力和增加消費執行個體數解決堆積問題後就不會出現這種堆積。

可以了解為消費能力已經飽和,其他隊列本身也有堆積情況,那麼飽和之後配置設定就會直接到指定的某個隊列。這種情況需要增加消費者或者優化代碼來提升能力減少堆積,堆積多肯定會更加滿負荷在跑。

這個上限不是擠壓的或者mq端大量堆積導緻程式高負載運作的上限,是正常消費有堆積就認為達到上限,是一個正常消費的理論上限。

這個是産品側的一個政策,無法做到堆積後再均衡對堆積量做進一步對均衡配置設定。建議增加消費執行個體或者優化代碼,減少堆積壓力。

廣播模式消費堆積

廣播模式下控制台顯示有大量堆積

【問題回答】:

廣播模式下控制台看到的這個堆積資料是無效的,廣播模式下服務端不維護消費進度,消費進度在用戶端維護,是以是否有堆積這個需要您用戶端來維護,廣播模式下我們服務端不維護消費進度,您的消費端的消費位點,我們這邊不儲存,這個隻能您自己消費端配置好消費日志,檢視消費情況的。

實時消息堆積量和各個具體消費端堆積量不一緻

消費者的實時消息堆積量有堆積量,但是各個具體的消費端卻顯示沒有堆積量。

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

實時消息堆積量是訂閱的整個topic的堆積量,包括重試隊列的

如果說這個gid曾經定閱過topicA,現在不訂閱A了,換成訂閱TopicB,那麼這個堆積量也是包含曾經訂閱A的堆積量

下面各個c端的堆積量,是精确到這個c端訂閱的tag的堆積量。下面的c端堆積量之和應該小于等于實施堆積量

【建議方案】:

可以點選這個消費者的【重置消費位點】,看下可以選擇到的topic是不是有目前沒有在訂閱的。如果有的話,可以把這個topic的位點清除下,那麼這個消費者的關于這個不再訂閱的topic的實時堆積量就會清除掉了

mq是否支援積壓消息後批量消費

開源RocketMQ 裡有 interval 積壓時間,可以積壓幾秒鐘再進行批量消費。

無序消費消息時,是否有參數可以設定Pull的實際間隔,進而保障拉取下來的消息有一定的量,而不是1個,主要目的是想提升批量。

有序分區消息時,是否支援批量的有序消費?

RocketMQ現在的消費模式本身就是push的

1、批量消費可在消費用戶端中設定ConsumeMessageBatchMaxSize 參數,批量消費消息個數。

批量拉取也要有對應的消息數才行,這個是在預期範圍内的。這個是根據當時隊列有多少條消息未消費來決定的,并不能做到每次消費的消息是一個固定值。PropertyKeyConst.ConsumeMessageBatchMaxSize 取值範圍為1-32

mq的消費邏輯是這樣的,啟動消費者之後,消費者會一直線上

如果topic當中一直沒有消息過來,我們會每15秒長輪詢一次,消費者主動到topic當中拉取消息。如果有消息,就會将消息拉取到進行消費。是以暫時不支援擠壓一定的消息之後再批量消費的

2、有序消息不支援批量消費

消費負載不均衡,有台消費者執行個體沒有消費消息

一個gid下面,多個消費端,有一/幾台機器顯示堆積量為0,其他的機器堆積量都很大

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

可以檢視下堆積量為0的機器的ons.log日志

通過關鍵字搜尋日志資訊(注意要找到對應的topic)

隻用關注其中的 perm 的值就行,6表示正常,如果是 4表示則表示mq後端做了相關的運維操作,後面會恢複正常的,此時沒有消費的用戶端可以拿來容災。

分區順序消息消費負載不均

三台同樣的機器,一台收到95%的消息,一台5%左右的消息,一台一直是0

個pod的代碼部署的是一樣的 就是一套代碼,都去作為消費者

三台機器的屬性是一模一樣,都是同一個業務

可能原因:

發送分區順序消息的時候, 指定的shardingKey不太合适。導緻消息發送打散的不夠均勻.,基本上都集中少量邏輯分區裡面了

shardingKey會影響消息分布在不同隊列,然後消費機器是對應到多個隊列的

發送分區順序消息指定sharding Key, 滿足業務限制的前提下, 盡量引進一些變量. 分布就會均勻了. 不是随機。

舉例來說: 如果是訂單系統. 用性别作為sharding key, 就不太合适. 如果user id/ 或者訂單号, 就是更好一些的選擇。

為什麼消費堆積顯示為負數?

【問題描述】:

為什麼消費堆積顯示的是負數

1、是否有删除過這個topic,如果之前已經使用了這個topic進行收發消息,後面又删除了,然後短時間内又建立了這個topic,就會導緻這個問題。可以通過重置消費位點來解決這個問題。

2、如果沒有,那麼需要提供執行個體id/地域/topic等資訊給到技術人員進行進一步的檢視

消費者rebalanceservice線程

在消費者線程當中看到rebalanceservice線程是正常的嗎?

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

這個是消費端負載均衡的線程。是一個正常狀态的線程。rebalance 是有時間間隔的

http協定消費者實時堆積量

http協定下的消費者實時堆積量都包含了那些?

這個堆積量是表示該消費者訂閱的topic當中的所有tag的總堆積量

舉例:topic當中有5個tag,該消費者指訂閱了其中1個,還有4個沒訂閱,但是這個四個沒訂閱的tag,在topic當中有堆積了,這個堆積量也會顯示在控制台當中的

消息投遞重試問題

如果消息業務消費時間太久,那過多久會重新投遞該消息

在訂閱消費消息時,假如消費這條消息需要10分鐘,那麼MQ大概多久會重新投遞該消息

消費端到mq當中拉到消息進行消費之後,會回報給mq已經成功拿到消息并且消費。如果mq沒有接收到消費端的回報,那麼mq就會認為這個消息沒有消費成功,那麼這個消息在topic當中就會再次可見,那麼消費者就可以再次來拉取這個消息(重試)

第一次發消息算是第0次,如果在10秒内沒有給mq回報,那麼這個消息就會再次可見,消費端就會再去拉取這個消息,就是第一次重試了,如果在10秒之後,消費者給了第一次發消息(第0次)的響應,那麼這個消費也是失敗的。比如消費者現在拉取到的是10s之後第一次重試的,那麼在之後的30秒之内,如果消費者給了mq第一次重試拉到的消息的響應,這個才算是消費成功的。

是以建議不要把業務邏輯放在傳回給mq消息的代碼之前,最好是保證10秒之内要給到mq響應。可以将業務邏輯放在其他地方做并發處理。

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

消息重複投遞

同一個消息有多次成功消費記錄

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

1、如果隻是偶爾有消息這樣,是因為絕大多數情況下,消息是不重複的。作為一款分布式消息中間件,在網絡抖動、應用處理逾時等異常情況下,無法保證消息不重複,但是能保證消息不丢失。

這種情況下,需要做好消費幂等,具體可以參考文檔:

https://help.aliyun.com/document_detail/44397.html?spm=5176.11065259.1996646101.searchclickresult.4a8f70e3uKZijr

2、如果是大量消息重複消費,需要核實您的代碼是否和mq官方提供的一緻,在重複消費消息的時候,消費端的網絡情況,是否有fullgc等

如果以上都沒有問題,則需要提供下具體的異常資訊:執行個體id/地域/topic/msgid等,給到技術支援人員進行确認

消息消費失敗,一直重試

消息消費失敗,一直消息重試,并且重試的間隔時間都是正常的

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

1、需要檢視下業務上關于這個消息有沒有什麼報錯,一般消費失敗是業務處理消息失敗,業務如果有問題,重試多少次還是會有問題的

2、可以檢視下ons.log日志,看下有沒有異常

3、需要檢查下消費的邏輯,傳回的狀态需要是Action.CommitMessage才對的

廣播模式消費失敗重試

有 A,B,C 3個節點, 使用廣播模式發送一條消息,實際的目标是 讓B處理, A和C直接放棄 , 那麼問題是A和C直接 Action.CommitMessage

掉這條消息後, B裡面業務處理出了問題 我消息Action.ReconsumeLater 後 消息是否會重發,重發是發給B 還是 A,B,C都會收到

廣播模式不支援消費失敗重投

消費失敗的消息沒有被重試

消費失敗的消息,一直沒有進行重試或者重試間隔的時間不對,與官方文檔提供的重試時間不符合

1、檢查下否是廣播消費模式,因為廣播方式不提供失敗重試特性,即消費失敗後,失敗消息不再重試,繼續消費新的消息。

2、如果确認使用的是叢集消費模式,檢查消費者啟動時的配置,是否有将最大重試次數

MaxReconsumeTimes的值設定為0,設定為0後将不在重試。這時可以去死信隊列裡确認下是否有此條消息。

3、如果配置沒問題,可以過會再去檢查消息軌迹,因為在共享叢集下,某個時間段broker壓力比較大的時候,消費失敗重試會有一定的延遲。可以多檢查下,确認沒有重試。

4、如果以上都确認沒有問題了,需要提供執行個體id/地域/topic/msgid等資訊給技術人員進行檢視

訂閱關系問題

訂閱關系不一緻

為什麼消費端不消費了/為什麼我的消息堆積了許多/為什麼消費速度不及預期,隻是偶爾消費一兩條/為什麼一條消息被重複消費了?

消費者的訂閱關系不一緻了

訂閱關系一緻指的是同一個消費者 Group ID 下所有 Consumer 執行個體的處理邏輯必須完全一緻。一旦訂閱關系不一緻,消息消費的邏輯就會混亂,甚至導緻消息丢失。

由于消息隊列 RocketMQ 版的訂閱關系主要由 Topic + Tag 共同組成,是以,保持訂閱關系一緻意味着同一個消費者 Group ID 下所有的消費者執行個體需在以下兩方面均保持一緻:

訂閱的 Topic 必須一緻

訂閱的 Topic 中的 Tag 必須一緻

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

http的消費者看不到訂閱關系

http的gid正在消費,但是topic當中檢視不到這個訂閱關系

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

http協定的消費者的訂閱關系控制台目前不支援顯示的

用戶端消費常見異常報錯

啟動消費端時報錯

啟動消費端時報錯找不到gid

2019-11-18 20:29:04,004 WARN RocketmqClient - execute the pull request exception

com.aliyun.openservices.shade.com.alibaba.rocketmq.client.exception.MQBrokerException: CODE: 26 DESC: subscription group [MQ_INST__BaSllRRw%GID_] does not exist,

See

http://rocketmq.apache.org/docs/faq/

for further details.

背景建立GID失敗了

【解決方案】:

可以在控制台當中将已經建立好的gid删除,在重新建立,建立完成之後,再次啟動消費端

消費線程被卡住

檢視消費者狀态—連接配接詳情,看到消費者存在消費線程被卡組和現象,卡住時間已超過10min25s

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

線程阻塞一般是CPU或記憶體消耗過高導緻,一般是業務代碼處理複雜和線程數較多導緻。

1、建議重新開機一下消費端看下堆積是否會降下去。

2、建議看看能否更新一下機器配置

3、優化一下接收到消息後的業務處理代碼

4、減少消費并發線程數目

消費者啟動後不消費

一個全新的消費者gid啟動,但是不消費已經發送到topic當中的消息

一個topic如果從來沒有任何一個gid連接配接消費過,假設這個topic當中已經有一千萬條消息發進來了,第一個啟動的gid是不會去消費這一千萬條消息的。是會從這個gid啟動當下開始,發送到tipic當中的消息開始消費

如果說這個topic已經有gid連接配接過了,如果再次啟動一個全新的gid連接配接,是會去消費topic當中還存在的,tag比對的消息的。

消費的時候,如何擷取消息體内容

以java代碼為例,可以使用new String(message.getBody())來擷取消息體内容

消費消息時ack報錯

消費消息時候ack報錯,ErrorMessage: The receipt handle you provided has expired.code MessageNotExist

報錯是消息句柄過期了,這個是通路逾時了

重新發送下這條消息,然後重新消費下。

全局順序消息為什麼啟動多個消費者隻有一個在消費

全局順序消息的topic下,一個gid啟動了多個消費者,但是隻有一個消費者在消費,其他的消費者都不消費?

全局順序建立topic時會指定到固定一台broker,隻會配置設定一個隊列。也就是說隻有一台消費者能消費到消息

全局順序消息,不管啟動幾個消費端,實際上都隻會有一個消費端來消費,也隻會配置設定到一個broker一個queue

此時多啟動的消費者可以用來容災

消費失敗的消息可以直接丢棄掉嗎?

消費失敗的消息可以手動丢棄掉嗎

直接catch異常,然後傳回成功,這個是有風險的,如果處理消息異常,會導緻不會再收到

消息預設重試16次後會進入死信隊列中,可以選擇重新發送或者三天後會自動清理,或者可以在生産者中try catch異常直接傳回成功狀态,該條消息則不會再重試和消費

消費者出現rebalanceService線程

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

這個是消費端負載均衡的線程,rebalance 是有時間間隔的

這個是正常的一個線程狀态

延遲消息被立馬/提前消費

發送的是延時消息,為何立馬就被消費端消費了或者設定的延時時間還沒有到就被消費了

1、确認發送延時消息的api是否和官方提供的demo是一緻的

2、是否設定了如圖所示的屬性

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

3、如果核實這兩者都沒有問題,需要将執行個體id/地域/topic/gid/發送代碼資訊收集完整,提供給技術支援進行檢視

順序消息沒有被順序消費

為什麼發送的順序消息,到那時消費的時候亂序了

1、檢查下發送消費的相關代碼,是否使用的是順序消息的api。收發順序消息

2、如果檢查發現使用的api都正确,這時可以通過消息軌迹和消息的存儲時間來判斷消息發送的先後順序。可能是當時發送時間的先後順序問題導緻您所認為的消費亂序。

3、如果以上都排查了,沒有問題,需要将執行個體id/地域/topic/gid/發送消費代碼提供給技術支援,進行進一步排查

消息一直沒有被消費

某條/些消息一直沒有被消費

1、檢查消費者是否線上

2、檢查消息的tag,該消費者是否有訂閱

3、檢查消費者是否訂閱關系保持一緻。一旦訂閱關系不一緻,消息消費的邏輯就會混亂,甚至導緻消息丢失。

4、業務上核實是否真的沒有收到該消息,mq是保證以消息準确到達服務端被消費為第一優先準則,是以在網絡環境較差或抖動的情況下,消息軌迹可能會丢失,根據消息軌迹查詢到的消費狀态是未消費,但是實際上該消息已經被消費了

消息沒有被立馬消費,延遲很久才被消費

消息發送時間到消費中間這段時間延遲比較久,例如上午發送的消息,到下午才被消費

1、檢視下發送的時間段,topic的發送量和消費量對比,看下是否處于一個業務高峰期,導緻消息有堆積,如果有消息堆積,那麼延遲投遞是正常現象

如果一直有堆積,建議增大消費能力,比如優化消費邏輯業務代碼,或者增加消費者機器

2、檢視ons.log日志,如果在ons.log中看到了

2019-07-05 16:46:39,039 WARN RocketmqClient - the cached message count exceeds the threshold 1000, so do flow control, minOffset=4731, maxOffset=5738, count=1008, size=0 MiB, pullRequest=PullRequest 【consumerGroup=GID_MR_SG_ACTIVITY_TEST, messageQueue=MessageQueue 【topic=T_MR_SG_USER_TASK_NORMAL_TEST, brokerName=hz-share2-03, queueId=7】, nextOffset=5739】, flowControlTimes=7235001。

這個警告是因為用戶端消費能力不足,導緻拉取消息也被暫停了。此時就需要增加消費能力,比如增加消費線程,或者增加消費者執行個體

3、檢視下是否是消費速度太低,可以根據消費者狀态當中的實時消費速度判斷,如果消費速度過低,那麼消息存放的隊列堆積就會比較嚴重,影響消費時間,建議配置上堆積監控。配置後超過多少堆積告警,或者考慮增加消費執行個體,讓消費能力稍微大于生成能力

重置消費位點失敗

重試消費者的消費位點沒有效果,還是有許多堆積

1、确認是否為叢集消費(因廣播模式下,消費位點都由用戶端本地維護,是以廣播消費模式下不支援重置消費位點)

2、确認目前消費者是否線上,消費者必須線上才能重置消費位點

3、确認sdk版本,sdk版本過低也會導緻此問題。(建議更新sdk,至少是1.8.0版本

4、可以點選單個c端的詳情檢視目前消費者當中的消息是否是在重試隊列當中的,如果選擇的是清除所有堆積消息,從最新位點開始消費方式重置消費位點,是不能清除重試隊列裡的消息的。這個時候可以選擇使用按時間點進行消費位點重置方式進行重置,此方式沒有這個限制。

同一條消息,為什麼發送方和訂閱方的msgid不一樣?

1檢查是否是事務消息或延時消息,如果是,則是正常現象。需要做幂等的話可以使用消息key來做幂等。事務消息或延時消息訂閱方的msgid取的是transactionId。

通過message.getMsgID()這個擷取的transactionId在控制台上是查不到消息的,這時候可以通過message.getUserProperties().getProperty("UNIQ_KEY")這個來擷取真正的msgid

2、因為某些sdk的原因,有可能發送方和訂閱方的msgid也會不一樣。任何類型的消息都是這樣,這時訂閱方的msgid是offsetmsgid。這個很好區分,transactionId中英文字母是小寫的,msgid和offsetmsgid中英文字母都是大寫的。

消費者顯示離線

檢視消費者狀态,發現消費者是離線狀态

1、消費者執行個體沒有啟動

2、路由資訊未注冊到NameServer上面

1.原因裡第一點直接啟動消費者皆可,

2.首先确認在MQ控制台已經建立了GID

3、用戶端可根據ons.log來排查是否有No route info of this topic的相關報錯資訊;

4、此時重點檢查執行個體化消費者參數時NAMESRV_ADDR 參數配置是否與MQ控制台上的一緻;排查接入點是否異常

步驟:删除用戶端日志------>重新開機應用----->檢視最新的ons.log。

同時确認NameServer是可連接配接的,telnet控制台提供的接入點看下是否telnet通。

如果不通,需要看下是不是該機器所屬地域與mq執行個體所屬不是同一個地域

ackmessage時報錯Number of receiptHandles in XML is out of range

http協定的RocketMQ ackmessage時傳回了 message: Number of receiptHandles in XML is out of range 錯誤

ack删除消息時,在xml body體中的receiptHandles數量大于16條。

一次最多是16個,超過就會報錯了

啟動消費端提示Group ID重複

啟動消息隊列Rocket MQ版的Producer(生産者)執行個體或Consumer(消費者)執行個體時,提示Group ID重複。

單個JVM程序中出現下列情況時,會導緻用戶端啟動失敗,提示Group ID重複:

啟動了一個以上的Producer執行個體,并且這些執行個體使用相同的Group ID。

啟動了一個以上的Consumer執行個體,并且這些執行個體使用相同的Group ID。

啟動了一個以上的Producer執行個體和一個以上的Consumer執行個體,并且這些執行個體使用相同的Group ID。

單個JVM程序中使用相同Group ID的Producer執行個體或Consumer執行個體支援情況如下表:

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

如果出現上述不支援的情況,請改正後重新啟動應用。

消費者啟動時提示擷取Topic隊列失敗

消息隊列RocketMQ版中Consumer(消費者)主動訂閱消息,啟動用戶端時系統提示擷取Topic隊列失敗。

導緻此問題的主要原因是用戶端中訂閱的Topic未在消息隊列RocketMQ版的控制台中建立。

1、登入消息隊列RocketMQ版的控制台,建立Topic和Group ID。

2、更新用戶端中訂閱的Topic和Group ID,確定其與控制台中建立的資訊一緻。

3、重新啟動用戶端,确認問題已經修複。

應用記憶體不足

1、在應用部署的機器上通過檢視記憶體已消耗完。

2、在/{user.home}/logs/ons.log能搜尋到 OutOfMemory 關鍵字。

3、在消息隊列 RocketMQ 版控制台:進入消費者管理 > 消費者狀态,堆積量欄顯示消息堆積較多,連接配接狀态欄顯示了各個已連接配接用戶端的消息堆積。通過 Jstack 排查, ConsumeMessageThread_ 線程無消費卡住現象。

【問題分析】:

在 1.7.0.Final 版本之前,預設用戶端最多會給每個 Topic 的每個隊列緩存 1000 條消息。假設每個 Topic 的隊列數是 16 個(叢集 2 主 2 備,每台 broker 上 8 個隊列),該 Topic 下單條消息平均大小為 64 KB,那麼最終該 Topic 在用戶端緩存的消息 Size:16 1000 64 KB = 1 GB。如果使用者同時訂閱了 8 個 Topic 都在用戶端記憶體緩存消息,最終占用記憶體将超過使用者的 JVM 配置,導緻 OOM。

原因 1:

依賴 1.7.0.Final 之前的 ons-client 版本,Topic 的平均消息大小超過 4 KB,并且消息消費較慢容易在用戶端記憶體緩存消息。

确認方式:

在 /{user.home}/logs/ons.log 能搜尋到 OutOfMemory 關鍵字;或者通過jmap -dump:live,format=b,file=heap.bin 指令确認哪些對象占用了大量記憶體。

恢複方案:

更新 ons-client 版本至 1.7.0.Final 或以上,同時給對應的 ConsumerBean 配合設定 com.aliyun.openservices.ons.api.PropertyKeyConst#MaxCachedMess ageSizeInMiB參數,然後重新開機應用。

原因 2:

依賴 1.7.0.Final 及以上的 ons-client 版本,預設最大消耗記憶體 512 MB(Group ID 訂閱的所有 Topic 緩存總和);如果應用仍然出現 OOM 現象,可在 ConsumerBean啟動時,配置:

com.aliyun.openservices.ons.api.PropertyKeyConst#MaxCachedMessageSizeInMiB參數自行定義最大消耗記憶體(範圍在 16 MB ~ 2048 MB)。

确認應用依賴的 ons-client 版本,并通過 JVM 确認給程序配置設定的記憶體大小。

根據應用機器的記憶體使用清況給對應的 ConsumerBean 設定com.aliyun.openservices.ons.api.PropertyKeyConst#MaxCachedMessageSizeInMiB參數,然後重新開機應用。

消費者報錯參數不合法

【異常及描述】:

參數不合法的情況有以下幾種:

1、異常:consumeThreadMin Out of range [1, 1000]

描述:消費端線程數設定不合理

2、異常:consumeThreadMax Out of range [1, 1000]

3、異常:messageListener is null

描述:未設定 messageListener

4、異常:consumerGroup is null

描述:未設定 Group ID

5、異常:msg delay time more than 40 day

描述:定時消息延時不能超過 40 天

消息顯示 _Consumed_, 但消費端未感覺到

消息狀态顯示“Consumed”,但是消費端業務日志顯示沒有收到消息。

1、業務代碼在接收到消息後,不立即列印消息

收到消息後,如果直接進入業務邏輯,一旦代碼遺漏某個邏輯分支,就會導緻消息資訊沒有被留在業務日志裡,造成沒有收到消息的假象。

建議您收到消息後,立即列印消息資訊留存 messageId, timestamp, reconsumeTime 等。

2、消費端部署了多個消費執行個體

尤其是在調試階段,消費端不可避免會多次重新開機,一旦多個消費程序同時存在(程序未退出),那麼相當于進入叢集的消費模式,多個消費執行個體會共同分擔消費消息。以為沒有收到的消息,其實是被另一個消費端接收了。

到消息隊列 RocketMQ 版控制台,進入Group 管理 > 消費者狀态 > 連接配接狀态,會顯示消費端的執行個體部署情況(有幾個消費執行個體,各自的連接配接 IP 等等),然後可以自行排查。

3、消息消費過程出現未被 Catch 的異常,導緻消息被重新投遞。

批量消費不起作用

使用的是批量消費的api BatchConsumer,為何每次消費的消息都是一條或者不是我設定的屬性 PropertyKeyConst.ConsumeMessageBatchMaxSize 的值?

這個是在預期範圍内的。這個是根據當時隊列有多少條消息未消費來決定的,并不能做到每次消費的消息是一個固定值。

PropertyKeyConst.ConsumeMessageBatchMaxSize 取值範圍為1-32

消息軌迹常見問題

消息軌迹顯示消費結果未傳回

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

消費消息的方法尚未傳回結果,或者中斷,導緻本次消費結果未傳回服務端

建議您不要把業務邏輯放在傳回給mq服務端的代碼之前,最好是保證盡快給到mq響應。這樣可以避免消息消費失敗,在進行消息重試。如果您的業務邏輯時間的确很長,建議您可以将資訊拉取到之後,存到資料庫、redis當中,然後盡快給到mq ackMessage,之後再異步進行業務消費。

消息已經消費,但是消費軌迹顯示尚未消費

消息本地日志記錄該消息已經完成消費,但是在控制台查詢消費軌迹卻顯示該消息尚未消費

1、首先确認發送方或訂閱方應用的sdk版本(1.2.7 版本及以上)

2、檢視發送端或消費端啟動時,将PropertyKeyConst.MsgTraceSwitch這個屬性值設定是否為false。這個屬性是啟用消息軌迹的開關。

3、如果sdk版本和發送端消費端執行個體化時參數配置都正常,可以讓檢視那個時間段的ons.log,檢查日志中是否有:

send trace data,the traceData is Pub ...

send trace data,the traceData is SubBefore ...

send trace data,the traceData is SubAfter ...

等等相關日志。出現了相關日志,說明消息軌迹發送失敗了。是以會缺失,不完整。

因為消息軌迹是異步發送的,存在的發送失敗的可能,具體以您業務中是否有被消費為準

軌迹消息在網絡不穩定,用戶端機器壓力大等一些情況下,可能存在發送失敗的可能性。因為軌迹消息重要性不及業務消息,這種情況一般不會重試,是以存在少量的消息無法采集到的情況。是以會看到上面的問題。後面我們會繼續優化。

批量導出消息的消費軌迹

需要批量導出某個topic某段時間内所有消息的消費軌迹

目前後端沒有存儲某個topic的消息軌迹,無法支援批量導出。

提供思路建議:

1、建立一個GID, 訂閱指定的topic. 控制台上Reset這個建立的gid的消費位

點到指定開始時間點. 消費程式調用 OpenAPI查詢軌迹資訊:

https://help.aliyun.com/document_detail/59830.html?spm=a2c4g.11186623.6.711.7fd27e80IBF0mT

2、注意一點, OpenAPI本身是運維接口, 需要控制查詢速度.

事務消息事務已送出,但是軌迹顯示事務未送出

事務消息事務已送出,但是軌迹顯示事務未送出。事務消息送出的軌迹記錄丢失 如下圖所示

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

事務消息的半消息存在db當中,消息commit的時候才會存到broker,但是軌迹是發到其他機器完成軌迹的記錄,收到軌迹記錄請求的目标機器并非原來發送方的機器,導緻軌迹記錄失敗

消息軌迹名詞解釋

關于消息軌迹名詞的解釋

消費問題排查 | 《Rocket MQ 使用排查指南》第三章

1、發送耗時:

這個耗時的時間是調用發送消息的com.aliyun.openservices.shade.com.alibaba.rocketmq.client.impl.MQClientAPIImpl#sendMessage() 的耗時時間。如果是同步發送,則會包含存儲到broker的時間,異步和oneWay 則不包含。

發送端的代碼邏輯可以看 DefaultMQProducerImpl.sendKernelImpl() 中執行的

com.aliyun.openservices.ons.api.impl.tracehook.OnsClientSendMessageHookImpl#sendMessageBefore

com.aliyun.openservices.ons.api.impl.tracehook.OnsClientSendMessageHookImpl#sendMessageAfter

2、消費耗時

這個時間是消費耗時,是調用用戶端的 consume() 的整個花費的時間。也就是圖2的 SubAfter 的 TimeStamp 減去 SubBefore 的 TimeStamp 的時間。

消費段的代碼邏輯可以看

com.aliyun.openservices.shade.com.alibaba.rocketmq.client.impl.consumer.ConsumeMessageConcurrentlyService.ConsumeRequest#run()(注意,這是非順序消費的執行邏輯) 中執行的

com.aliyun.openservices.ons.api.impl.tracehook.OnsConsumeMessageHookImpl#consumeMessageBefore

com.aliyun.openservices.ons.api.impl.tracehook.OnsConsumeMessageHookImpl#consumeMessageAfter

3、消費軌迹的ip就是本機ip。linux環境下利用 ifconfig 檢視,windows環境利用ipconfig檢視

消息軌迹中記錄消費的ip與實際消費該消息的ip不一緻

消息軌迹當中記錄的消費端的消費ip與實際業務上消費該消息的機器的ip不一緻

如果消費消息的ecs當中有docker,mq取的用戶端Ip會取到docker網卡的ip,而不是ecs的内網ip

這個是您運作環境下拿出來的ip,如果是docker環境,不一定是真實ip

具體消費的ip以實際您自己業務當中記錄的ip為準