rabbitmq 重试机制

前言

在消息传递过程中,可能会遇到各种问题,如网络故障,服务不可用,资源不足等,这些问题可能导致消息处理失败.为了解决这些问题,RabbitMQ提供了重试机制,允许消息在处理失败后重新发送.

但如果是程序逻辑引起的错误,那么多次重试也是没有用的,如果重复入队反复消费这是不可取的,因此我们可以设置重试次数

配置信息

我们先将 确认模式调成默认的 (auto)

java 复制代码
spring:
  rabbitmq:
    addresses: xxxx
    listener:
      simple:
        acknowledge-mode: auto # 设置确认模式
        retry:
          enabled: true # 开启消费者失败重试
          initial-interval: 5000ms # 初始失败等待时长为5秒
          max-attempts: 5 # 最大重试次数 包括(包括自身消费的⼀次) 

initial-interval 和 max-attempts 大家可以自行发挥

这里的最大重试次数包括自身消费的一次,是指,第一次发送给消费者也算进重试次数

代码演示

AUTO 模式

常量类:

java 复制代码
    //消息退回
    public static final String RETRY_QUEUE = "RETRY_QUEUE";

声明队列:

java 复制代码
    //重试机制
    @Bean("retryQueue")
    public Queue retryQueue() {
        return QueueBuilder.durable(MQConstants.RETRY_QUEUE).build();
    }

生产者:

java 复制代码
    @RequestMapping("/retry")
    public String retry() {
        rabbitTemplate.convertAndSend("", MQConstants.RETRY_QUEUE, "retry");
        return "消息发送成功";
    }

消费者:

java 复制代码
@Component
@RabbitListener(queues = "RETRY_QUEUE")
public class RetryListener {
    @RabbitHandler
    public void handle(String messageContent, Channel channel, Message message) throws IOException {
        System.out.println("接收到的消息:" + messageContent);
        int n = 10 / 0; //添加异常,观察重试
        System.out.println("消息消费成功");
    }
}

运行程序观察:

在AUTO模式下,重试次数达到指定次数之后,就会将消息丢弃

NONE 模式

配置信息:

java 复制代码
spring:
  application:
    name: abbitExtensionDemo
  rabbitmq:
    addresses: xxxx
    listener:
      simple:
        acknowledge-mode: none  # 设置确认模式
        retry:
          enabled: true # 开启消费者失败重试
          initial-interval: 5000ms # 初始失败等待时长为5秒
          max-attempts: 5 # 最大重试次数

NONE 和 AUTO 模式一样,消息达到重试次数之后,就会自动丢弃

自动确认模式下,RabbitMQ会在消息被投递给消费者后自动确认消息,如果消费者处理消息时抛出异常,RabbitMQ根据配置的重试参数自动将消息重新入队,从而实现重试.重试次数和重试间隔等参数可以直接在RabbitMQ的配置中设定,并且RabbitMQ会负责执行这些重试策略。

MAMUAL 模式

配置信息

java 复制代码
spring:
  application:
    name: abbitExtensionDemo
  rabbitmq:
    addresses: xxxx
    listener:
      simple:
        acknowledge-mode: manual  # 设置确认模式
        retry:
          enabled: true # 开启消费者失败重试
          initial-interval: 5000ms # 初始失败等待时长为5秒
          max-attempts: 5 # 最大重试次数

消费者使用手动确认机制:

java 复制代码
@Component
@RabbitListener(queues = "RETRY_QUEUE")
public class RetryListener {
    @RabbitHandler
    public void handle(String messageContent, Channel channel, Message message) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            System.out.println("接收到的消息:" + messageContent);
            int n = 10 / 0;
            System.out.println("消息消费成功");
            channel.basicAck(deliveryTag, false);
        } catch (Exception e) {
            channel.basicNack(deliveryTag, false, true);
        }
    }
}


这里也不受重试次数的限制,一直重新入队

这里的 unacked 是指没有收到确认的消息,不是收到否定确认的消息数量,否定确认和肯定确认都是确认,大家不要混淆


当我们将设置不重新入队的时候:

java 复制代码
channel.basicNack(deliveryTag, false, false);

消息没有进行重试,并且队列也为空了


可以看到,手动确认模式时,重试次数的限制不会像在自动确认模式下那样直接生效,因为是否重试以及何时重试更多地取决于应用程序的逻辑和消费者的实现.

手动确认模式下,消费者需要显式地对消息进行确认,如果消费者在处理消息时遇到异常,可以选择不确认消息使消息可以重新入队,重试的控制权在于应用程序本身,而不是RabbitMQ的内部机制.应用程序可以通过自己的逻辑和利用RabbitMQ的高级特性来实现有效的重试策略

总结

使用重试机制时需要注意:
1.自动确认和默认模式下:程序逻辑异常,多次重试还是失败,消息就会被自动确认,那么消息就丢失
2. 手动确认模式下:程序逻辑异常,多次重试消息依然处理失败,无法被确认,就一直是unacked的状态,导致消息积压

相关推荐
iiYcyk7 小时前
RabbitMQ之死信队列
分布式·rabbitmq
hong_zc19 小时前
RabbitMQ工作模式(下)
rabbitmq
Cxzzzzzzzzzz1 天前
RabbitMQ 入门与 Go 语言实践
golang·rabbitmq·ruby
零千叶2 天前
【面试】RabbitMQ 常见问题
面试·职场和发展·rabbitmq
kobe_OKOK_2 天前
rabbitmq 入门知识点
分布式·rabbitmq·ruby
王嘉俊9252 天前
深入浅出 全面剖析消息队列(Kafka,RabbitMQ,RocketMQ 等)
分布式·kafka·消息队列·rabbitmq·rocketmq
Zhao_yani2 天前
RabbitMQ相关知识
分布式·rabbitmq
孤独的复仇者2 天前
RabbitMQ高级:延迟消息
分布式·rabbitmq
AAA修煤气灶刘哥3 天前
后端哭晕:超时订单取消踩过的坑,延迟消息这么玩才对!
后端·spring cloud·rabbitmq