RabbitMQ 在以下情况下会进行消息重试:
  • 消费者显式抛出异常:当消费者显式抛出异常时,RabbitMQ 会触发重试机制。例如,当消费者发送消息时报错,可以通过 basic.reject 或 basic.nack 方法拒绝消息并设置 requeue = true 来触发重试。
  • 消息被拒绝后重新加入队列:当消息被 RabbitMQ 的 reject 或 nack 方法拒绝后,消息会被重新加入到队列中,并设置 requeue = true。但是,如果消费者在重新加入队列后没有再次发送消息,则重试机制不会触发。
  • 消息队列达到最大长度:当队列中的消息数量达到了最大长度时,RabbitMQ 会触发重试机制。这时候,RabbitMQ 会将队列中的消息移动到其他队列中,并设置 requeue = true,触发重试。
  • 达到最大重试限制:当消息在队列中被拒绝次数达到了最大重试限制时,RabbitMQ 会触发重试机制。这时候,RabbitMQ 会将队列中的消息放入死信队列中,并设置 requeue = false,触发重试。

需要注意的是,当消费者在一段时间内没有再次发送消息时,RabbitMQ 会认为消费者已经放弃了这个消息,不会再次重试。因此,在使用 RabbitMQ 进行生产者时,需要考虑消费者的重试策略,以提高消息的到达率和成功率。

消费端在处理消息过程中可能会报错,此时该如何重新处理消息呢?解决方案有以下两种。

  • 在redis或者数据库中记录重试次数,达到最大重试次数以后消息进入死信队列或者其他队列,再单独针对这些消息进行处理;

  • 使用spring-rabbit中自带的retry功能;

第一种方案我们就不再详细说了,我们主要来看一下第二种方案,老规矩,先上代码:

spring:
  rabbitmq:
    listener:
      simple:
        #NONE:自动确认;AUTO:根据情况确认;MANUAL:手动确认
        acknowledge-mode: auto
        # 消费者重试配置
        retry:
          # 开启重试,默认是false
          enabled: true
          # 重试次数,默认为3次
          max-attempts: 5
           # 重试最大间隔时间
          max-interval: 10000
          # 第一次重试的时间间隔(毫秒)
          initial-interval: 2000
          # 间隔时间乘子,间隔时间*乘子=下一次的间隔时间,最大不能超过设置的最大间隔时间
          multiplier: 2.0

此时我们的消费者代码如下所示:

@RabbitHandler
@RabbitListener(queues = {"${platform.queue-name}"},concurrency = "1")
public void msgConsumer(String msg, Channel channel, Message message) throws IOException {
        log.info("接收到消息>>>{}",msg);
        int temp = 10/0;
        log.info("消息{}消费成功",msg);
}
作者:Jeebiz  创建时间:2023-04-04 11:49
最后编辑:Jeebiz  更新时间:2024-11-01 10:06