一、消費流程圖
消息在消費出現異常的時候,將一直保留在消息隊列,所以你會看到以下奇怪的現象:
消息隊列僅有5個消息, 投遞速度也非常快,結果卻一直無法消費掉。
二、重試策略
重試機制的使用場景:重試機制適用于那些可能因為臨時問題(如網絡問題、外部服務不可用等)導致處理失敗的情況。
自定義重試邏輯:可以通過自定義錯誤處理器(如 RepublishMessageRecoverer)來實現更復雜的重試邏輯,例如記錄重試次數并根據條件決定是否重新投遞。
無限重試可能導致問題:如果消息本身存在問題(如格式錯誤),無限重試會導致大量日志輸出,且可能阻塞隊列。
本文就是中了此招,帶來的后果就是SLS費用劇增。
1、重試次數
開啟重試,設置重試的次數、間隔時間。
在計算間隔時間的時候,使用指數級增長,而非簡單的倍數。
listener:simple:retry:enabled: truemax-attempts: 5 # 最大重試次數initial-interval: 10000 # 初始重試間隔(毫秒)max-interval: 30000 # 最大重試間隔(毫秒)multiplier: 3 # 重試間隔的乘數因子
2、死信隊列
為了避免消息無限重試,建議配置死信隊列。當消息達到最大重試次數后,將其發送到死信隊列,以便后續處理。
listener:simple:default-requeue-rejected: false
通過合理配置重試機制和死信隊列,可以有效避免消息無限重試導致的問題,同時確保消息的可靠處理。
建立死信消息監聽者,對消息的最后處理,如果還是失敗,則發送告警消息給相關人員。
當消費者在處理消息時拋出異常且達到最大重試次數后,消息會被拒絕并發送到死信隊列,從而避免消息丟失并便于后續處理。
三、消息確認模式
在 Spring AMQP 的默認配置中,acknowledge-mode 的默認值是 AUTO,即自動確認模式。
最終rabbitmq的配置見下:
listener:simple:retry:enabled: truemax-attempts: 5initial-interval: 10000max-interval: 30000multiplier: 3acknowledge-mode: autodefault-requeue-rejected: false
自動確認模式(AUTO)
在自動確認模式下,當消費者接收到消息后,Spring AMQP 會自動向 RabbitMQ 發送確認消息(ACK),表示消息已被成功消費。這意味著:
- 優點:實現簡單,不需要手動確認消息,適合簡單的消費場景。
- 缺點:如果消費者在處理消息時拋出異常,消息會被認為已經消費成功,從隊列中移除,不會重新投遞。這可能導致消息丟失。
手動確認模式(MANUAL)
在手動確認模式下,消費者需要顯式地調用確認方法(basicAck 或 basicNack)來確認消息。這意味著:
- 優點:可以更靈活地控制消息的確認時機,確保消息在成功處理后才被確認,從而避免消息丟失。
- 缺點:實現相對復雜,需要在代碼中手動處理確認邏輯。
四、總結
消息在消費的時候,如果出現異常,直接拋棄,不想進入重試流程。
你可能會配置修改如下:
listener:simple:retry:enabled: false
回到最上面的流程圖,其實還是無法解決消息消費失敗的死循環。
雖然不會進入重試, 但是在消費消息的時候,由于拋異常,又會進入消息隊列。
最終導致死循環。
解決方法是: 對于不想要重試,而又不陷入死循環。那么就只有一個辦法,使用個大大的try-catch住消息監聽方法。