<form id="jrvnn"></form>

        <address id="jrvnn"><listing id="jrvnn"></listing></address>
        <form id="jrvnn"><nobr id="jrvnn"><meter id="jrvnn"></meter></nobr></form>

          <sub id="jrvnn"><listing id="jrvnn"></listing></sub>

                RocketMQ Spring Starter消費堆積引發的系統思考和處理(1)

                小編:管理員 51閱讀 2022.08.01

                在使用RocketMQ的過程中,消費堆積問題是不可避免的問題。這次借機分享下如何系統思考和解決問題,各位方家指正。

                我本地已經復現了該問題,這里以一個復現的app做分享和解釋。主要包含

                1. 復現問題
                2. 問題描述
                3. 問題分析
                4. 翻看源碼確認問題
                5. 解決問題
                  1. 臨時解決 --- 變通解
                  2. 長期解決 --- 提PR徹底解
                6. 周邊問題確認

                本文涉及rocketmq dashboard代碼、rocketmq admin tool代碼、broker代碼、client代碼、client&broker心跳源碼等,建議坐地鐵時翻看,有問題隨時留言。

                1. 復現問題:這一步靠經驗吧。

                https://github.com/rocketmq101/spring-issue-405

                2. 問題描述

                用戶在使用RocketMQ Spring 2.2.1的時候發現消費堆積,異常截圖如下:

                消費詳情一直不變,并且始終消費不到queue 0, queue 1:

                消費者實例:啟動了一個push消費者,消費者client卻有兩個。

                用戶使用的代碼:

                用戶配置:

                3. 初步分析

                某種原因導致啟動了兩個消費者實例,并且會導致訂閱關系不一致。

                可能性1:

                根據以往的經驗,訂閱關系不一致,會導致全部的消費者在分配queue-消費者實例的時候出現混亂,導致訂閱錯亂,所以有的queue沒有消費者消費。

                此時重溫下什么是訂閱關系:在一個消費者組中,消費者組-topic-tag在每個消費者實例啟動時必須保持一致。

                經過排查,這個消費者訂閱關系一致,排除掉。

                可能性2:

                Push消費者和Pull消費者同時存在。導致用戶使用的Push消費者只消費到了一部分queue,另一部分由Pull消費者分配了,但是沒有展示。

                為什么這么猜測?

                首先,源自于flink消費kafka的邏輯,在flink消費kafka時,kafka-manager上是看不到消費者的。flink消費kafka實際是pull的,猜測RocketMQ和kafka這里邏輯一樣。

                其次,RocketMQ隊列分配邏輯:每個消費者將自己注冊到broker中,啟動reblance時,全部的queue按照一定的原則分配給全部的消費者實例。Pull和Push消費者是否一起當作消費者分配了不同的隊列呢?

                這個猜測最后通過排查rocketmq-dashboad、rocketmq broker、rocketmq client的代碼后確認了此邏輯。

                4. 源碼翻看。

                4.1 RocketMQ Spring源碼確認問題

                翻看github issue,可以找到:https://github.com/apache/rocketmq-spring/issues/450有相似問題。這個問題目前筆者已經提PR修復了,歡迎大家使用新版本的RocketMQ Spring。

                翻看源碼后,確認了一個惡心的邏輯。

                惡心邏輯:如果rocketmq-spring配置項中包含了下面三個配置項時,會默認啟動一個DefaultLitePullConsumer實例。

                rocketmq.name-server=127.0.0.1:9876
                rocketmq.consumer.group=test-group
                rocketmq.consumer.topic=test-topic
                復制

                總結:所以可以解釋通現象中明明只配置了一個PushConsumer,但是啟動了2個Client實例。

                4.2 Broker4.9.3 源碼,確認日志。

                其實消費者在啟動注冊到Broker的時候, 會打印日志:

                如果啟動很久了,日志可能被刪除了,重啟下消費者就會看到。

                5. 問題處理

                如果處理呢?在配置RocketMQ Spring 時,只要以下三個配置項不同時存在就行了(這里吐槽Spring的條件注解,非常好用,也非常容易滋生暗。

                rocketmq.name-server=127.0.0.1:9876
                rocketmq.consumer.group=test-group
                rocketmq.consumer.topic=test-topic
                復制

                一般處理到這里就完了。下面是我提的兩個問題:

                第一個問題:如何徹底解這個問題呢?

                當然是提交代碼,合并到社區,新版本會徹底修掉這個bug,大家也不會再遇到這個問題。

                目前代碼已經合并到社區,歡迎大家閱讀指正:

                https://github.com/apache/rocketmq-spring/pull/459。

                這個修改的指導思想是:配置項功能需要簡單、明確,一個配置項就干一個事情。

                第二個問題:在消費詳情中,為什么Pull消費者在Dashboard中不顯示消費者client和queue的關系信息呢?

                實際下圖的空白中,是Pull消費者消費的,卻沒有consumerClient。

                第三個問題:在消費者實例列表中,明明Pull和Push消費者的ConsumerType不一樣,為什么這里只顯示了CONSUME_ACTIVELY(Pull)

                CONSUME_ACTIVELY為什么表示Pull,請看代碼:

                第二,三個問題將在下一篇繼續介紹。

                關聯標簽:
                皇宫里的共享小公主

                  <form id="jrvnn"></form>

                      <address id="jrvnn"><listing id="jrvnn"></listing></address>
                      <form id="jrvnn"><nobr id="jrvnn"><meter id="jrvnn"></meter></nobr></form>

                        <sub id="jrvnn"><listing id="jrvnn"></listing></sub>