消息队列中消息消费失败后的处理机制

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

参考文档

  1. RocketMQ消费消息失败的处理办法
  2. RabbitMQ的消息确认机制
  3. RabbitMQ与Spring、SpringBoot整合时的坑及注意点
原文地址:https://www.cnblogs.com/haycheng/p/13755679.html