本文主要介紹雲訊息佇列 RocketMQ 版TCP協議的Java用戶端使用過程中,經常會出現的訊息堆積和訊息延遲的問題。通過瞭解雲訊息佇列 RocketMQ 版用戶端的消費原理和訊息堆積的主要原因,協助您可以在業務部署前更好的規劃資源和配置,或在營運過程中及時調整商務邏輯,避免因訊息堆積和延遲影響業務運行。
背景資訊
- 業務系統上下遊能力不匹配造成的持續堆積,且無法自行恢複。
- 業務系統對訊息的消費即時性要求較高,即使是短暫的堆積造成的訊息延遲也無法接受。
用戶端消費原理
- 階段一:擷取訊息,SDK用戶端通過長輪詢批量拉取的方式從雲訊息佇列 RocketMQ 版服務端擷取訊息,將拉取到的訊息緩衝到本地緩衝隊列中。
SDK擷取訊息的方式為批量拉取,常見內網環境下都會有很高的輸送量,例如:1個單線程單分區的低規格機器(4C8GB)可以達到幾萬TPS,如果是多個分區可以達到幾十萬TPS。所以這一階段一般不會成為訊息堆積的瓶頸。
- 階段二:提交消費線程,SDK用戶端將本機快取的訊息提交到消費線程中,使用業務消費邏輯進行處理。
此時用戶端的消費能力就完全依賴於商務邏輯的複雜度(消費耗時)和消費邏輯並發度了。如果業務處理邏輯複雜,處理單條訊息耗時都較長,則整體的訊息輸送量肯定不會高,此時就會導致用戶端本地緩衝隊列達到上限,停止從服務端拉取訊息。
消費耗時
- 讀寫外部資料庫,例如MySQL資料庫讀寫。
- 讀寫外部緩衝等系統,例如Redis讀寫。
- 下遊系統調用,例如Dubbo調用或者下遊HTTP介面調用。
例如:某業務消費邏輯中需要寫一條資料到資料庫,單次消費耗時為1 ms,平時訊息量小未出現異常。業務側進行大促活動時,寫資料庫TPS爆髮式增長,並很快達到資料庫容量限制,導致消費單條訊息的耗時增加到100 ms,業務側可以明顯感受到消費速度大幅下跌。此時僅通過調整雲訊息佇列 RocketMQ 版SDK的消費並發度並不能解決問題,需要對資料庫容量進行升配才能從根本上提高用戶端消費能力。
消費並發度
訊息類型 | 消費並發度 |
普通訊息 | 單節點線程數*節點數量 |
定時和延時訊息 | |
事務訊息 | |
順序訊息 | Min(單節點線程數*節點數量,分區數) |
- 單機vCPU核心數為C。
- 線程切換耗時忽略不計,I/O操作不消耗CPU。
- 線程有足夠訊息等待處理,且記憶體充足。
- 邏輯中CPU計算耗時為T1,外部I/O操作為T2。
如何避免訊息堆積和延遲
為了避免在業務使用時出現非預期的訊息堆積和延遲問題,您需要在前期設計階段對整個商務邏輯進行完善的排查和梳理。整理出正常業務運行情境下的效能基準,才能在故障情境下迅速定位到阻塞點。其中最重要的就是梳理訊息的消費耗時和訊息消費的並發度。
- 梳理訊息的消費耗時通過壓測擷取訊息的消費耗時,並對耗時較高的操作的代碼邏輯進行分析。查詢消費耗時,請參見擷取訊息消費耗時。梳理訊息的消費耗時需要關注以下資訊:
- 訊息消費邏輯的計算複雜度是否過高,代碼是否存在無限迴圈和遞迴等缺陷。
- 訊息消費邏輯中的I/O操作(如:外部調用、讀寫儲存等)是否是必須的,能否用本機快取等方案規避。
- 消費邏輯中的複雜耗時的操作是否可以做非同步化處理,如果可以是否會造成邏輯錯亂(消費完成但非同步作業未完成)。
- 設定訊息的消費並發度
- 逐步調大線程的單個節點的線程數,並觀測節點的系統指標,得到單個節點最優的消費線程數和訊息輸送量。
- 得到單個節點的最優線程數和訊息輸送量後,根據上下遊鏈路的流量峰值計算出需要設定的節點數,節點數=流量峰值/單線程訊息輸送量。
如何解決訊息堆積和延遲問題
想要快速避免訊息堆積和延遲給業務帶來的影響,您可以通過雲訊息佇列 RocketMQ 版提供的監控警示功能,設定警示規則提前預警訊息堆積問題,或通過業務埋點,觸發警示事件,及時監控到訊息堆積問題並進行處理。設定警示規則,請參見監控警示。
若收到訊息堆積警示,處理方法,請參見如何處理訊息堆積。