本文為您介紹云消息隊列 RocketMQ 版的消息發(fā)送重試機制和消息流控機制。

背景信息

消息發(fā)送重試

云消息隊列 RocketMQ 版的消息發(fā)送重試機制主要為您解答如下問題:
  • 部分節(jié)點異常是否影響消息發(fā)送?
  • 請求重試是否會阻塞業(yè)務調(diào)用?
  • 請求重試會帶來什么不足?

消息流控

云消息隊列 RocketMQ 版的流控機制主要為您解答如下問題:
  • 系統(tǒng)在什么情況下會觸發(fā)流控?
  • 觸發(fā)流控時客戶端行為是什么?
  • 應該如何避免觸發(fā)流控,以及如何應對突發(fā)流控?

消息發(fā)送重試機制

重試基本概念

云消息隊列 RocketMQ 版客戶端連接服務端發(fā)起消息發(fā)送請求時,可能會因為網(wǎng)絡故障、服務異常等原因?qū)е抡{(diào)用失敗。為保證消息的可靠性,云消息隊列 RocketMQ 版在客戶端SDK中內(nèi)置請求重試邏輯,嘗試通過重試發(fā)送達到最終調(diào)用成功的效果。

同步發(fā)送和異步發(fā)送模式均支持消息發(fā)送重試。

重試觸發(fā)條件

觸發(fā)消息發(fā)送重試機制的條件如下:
  • 客戶端消息發(fā)送請求調(diào)用失敗或請求超時
    • 網(wǎng)絡異常造成連接失敗或請求超時。
    • 服務端節(jié)點處于重啟或下線等狀態(tài)造成連接失敗。
    • 服務端運行慢造成請求超時。
  • 服務端返回失敗錯誤碼
    • 系統(tǒng)邏輯錯誤:因運行邏輯不正確造成的錯誤。
    • 系統(tǒng)流控錯誤:因容量超限造成的流控錯誤。
說明 對于事務消息,只會進行透明重試(transparent retries),網(wǎng)絡超時或異常等場景不會進行重試。

重試流程

生產(chǎn)者在初始化時設置消息發(fā)送最大重試次數(shù),當出現(xiàn)上述觸發(fā)條件的場景時,生產(chǎn)者客戶端會按照設置的重試次數(shù)一直重試發(fā)送消息,直到消息發(fā)送成功或達到最大重試次數(shù)重試結(jié)束,并在最后一次重試失敗后返回調(diào)用錯誤響應。

  • 同步發(fā)送:調(diào)用線程會一直阻塞,直到某次重試成功或最終重試失敗,拋出錯誤碼和異常。
  • 異步發(fā)送:調(diào)用線程不會阻塞,但調(diào)用結(jié)果會通過異常事件或者成功事件返回。

重試間隔

  • 除服務端返回系統(tǒng)流控錯誤場景,其他觸發(fā)條件觸發(fā)重試后,均會立即進行重試,無等待間隔。
  • 若由于服務端返回流控錯誤觸發(fā)重試,系統(tǒng)會按照指數(shù)退避策略進行延遲重試。
    指數(shù)退避算法通過以下參數(shù)控制重試行為:
    • INITIAL_BACKOFF: 第一次失敗重試前后需等待多久,默認值:1秒。
    • MULTIPLIER :指數(shù)退避因子,即退避倍率,默認值:1.6。
    • JITTER :隨機抖動因子,默認值:0.2。
    • MAX_BACKOFF :等待間隔時間上限,默認值:120秒
    • MIN_CONNECT_TIMEOUT :最短重試間隔,默認值:20秒。
    建議算法如下:
    ConnectWithBackoff()
      current_backoff = INITIAL_BACKOFF
      current_deadline = now() + INITIAL_BACKOFF
      while (TryConnect(Max(current_deadline, now() + MIN_CONNECT_TIMEOUT))!= SUCCESS)
        SleepUntil(current_deadline)
        current_backoff = Min(current_backoff * MULTIPLIER, MAX_BACKOFF)
        current_deadline = now() + current_backoff + UniformRandom(-JITTER * current_backoff, JITTER * current_backoff)

    更多信息,請參見connection-backoff.md

功能約束

  • 鏈路耗時阻塞評估:從上述重試機制可以看出,在重試流程中生產(chǎn)者僅能控制最大重試次數(shù)。若由于系統(tǒng)異常觸發(fā)了SDK內(nèi)置的重試邏輯,則服務端需要等待最終重試結(jié)果,可能會導致消息發(fā)送請求鏈路被阻塞。對于某些實時調(diào)用類場景,您需要合理評估每次調(diào)用請求的超時時間以及最大重試次數(shù),避免影響全鏈路的耗時。
  • 最終異常兜底:云消息隊列 RocketMQ 版客戶端內(nèi)置的發(fā)送請求重試機制并不能保證消息發(fā)送一定成功。當最終重試仍然失敗時,業(yè)務方調(diào)用需要捕獲異常,并做好冗余保護處理,避免消息發(fā)送結(jié)果不一致。
  • 消息重復問題:因遠程調(diào)用的不確定性,當云消息隊列 RocketMQ 版客戶端因請求超時觸發(fā)消息發(fā)送重試流程,此時客戶端無法感知服務端的處理結(jié)果,客戶端進行的消息發(fā)送重試可能會產(chǎn)生消息重復問題,業(yè)務邏輯需要自行處理消息重復問題。

消息流控機制

消息流控基本概念

消息流控指的是系統(tǒng)容量或水位過高,云消息隊列 RocketMQ 版服務端會通過快速失敗返回流控錯誤來避免底層資源承受過高壓力。

觸發(fā)條件

云消息隊列 RocketMQ 版的消息流控觸發(fā)條件如下:
  • 存儲壓力大:參考消費進度管理的原理機制,消費者分組的初始消費位點為當前隊列的最大消費位點。若某些場景例如業(yè)務上新等需要回溯到指定時刻前開始消費,此時隊列的存儲壓力會瞬間飆升,觸發(fā)消息流控。
  • 服務端請求任務排隊溢出:若消費者消費能力不足,導致隊列中有大量堆積消息,當堆積消息超過一定數(shù)量后會觸發(fā)消息流控,減少下游消費系統(tǒng)壓力。

流控行為

當系統(tǒng)觸發(fā)消息發(fā)送流控時,客戶端會收到系統(tǒng)限流錯誤和異常,錯誤碼信息如下:
  • reply-code:530
  • reply-text:TOO_MANY_REQUESTS

客戶端收到系統(tǒng)流控錯誤碼后,會根據(jù)指數(shù)退避策略進行消息發(fā)送重試

處理建議

  • 如何避免觸發(fā)消息流控:觸發(fā)限流的根本原因是系統(tǒng)容量或水位過高,您可以利用可觀測性功能監(jiān)控系統(tǒng)水位容量等,保證底層資源充足,避免觸發(fā)流控機制。
  • 突發(fā)消息流控處理:如果因為突發(fā)原因觸發(fā)消息流控,且客戶端內(nèi)置的重試流程執(zhí)行失敗,則建議業(yè)務方將請求調(diào)用臨時替換到其他系統(tǒng)進行應急處理。