RocketMQ 中的機制
RocketMQ 中,消息消費結果的返回值有2個:ConsumeConcurrentlyStatus.CONSUME_SUCCESS 和 ConsumeConcurrentlyStatus.RECONSUME_LATER。
前者為消費成功,後者表示消費失敗。消費失敗后,RocketMQ會在特定時間間隔后進行重試,重試次數越多,時間間隔越長。
默認最多可以重試16次,每次重試的時間間隔為:
messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h
RabbitMQ 中的機制
RabbitMQ 中,消息消費確認模式有如下3種:
- AcknowledgeMode.NONE:不確認
- AcknowledgeMode.AUTO:自動確認
- AcknowledgeMode.MANUAL:手動確認
在Spring Boot中配置消費確認模式的配置:
spring.rabbitmq.listener.simple.acknowledge-mode=manual
手動確認模式中,如果消息消費失敗,可以選擇是否將消息重新放入隊列。
默認的確認模式為自動確認,如果消息消費的方法執行完成而未拋出異常,則會自動確認該消息消費成功;若拋出異常,則會自動確認消費失敗,此時消息會重新回到隊列中(按默認配置)。
消息消費失敗后如果重新放入隊列,RabbitMQ會立刻將消息重新推送給消費者,而沒有延遲推送的機制。
此時很可能會出現一直失敗並拋出異常的情況,浪費了資源,並導致日志爆滿,並淹沒最初幾條有用的異常日志信息(Java中如果多次拋出同樣的異常,打印日志時會省略部分異常堆棧)。
因此為了方便查看完整的異常堆棧,進程錯誤排查,建議在RabbitMQ消息消費失敗時,不要無限次的放回隊列。此時有以下兩種場景:
手動確認模式下
消費失敗時,不將其重新放入隊列(確認重試也不會成功的情形),打印錯誤信息后,通知相關人員,人工介入處理。
自動確認模式下
在Spring Boot RabbitMQ中,可以通過以下幾個配置參數,來調節消息消費失敗時,消息重新投遞的策略:
# 是否開啟消費者重試(為false時關閉消費者重試)
spring.rabbitmq.listener.simple.retry.enabled=true
# 最大重試重新投遞消息次數
spring.rabbitmq.listener.simple.retry.max-attempts=3
# 重試重新投遞消息的間隔時間(單位毫秒)
spring.rabbitmq.listener.simple.retry.initial-interval=5000ms
#重試次數超過上面的設置之后,是否丟棄(消費者listener拋出異常,是否重回隊列(默認true:重回隊列,false:不重回隊列(可結合死信交換機))
spring.rabbitmq.listener.simple.default-requeue-rejected=false