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的状态,导致消息积压

相关推荐
爱琴孩11 分钟前
RabbitMQ 消息消费模式深度解析
rabbitmq·消息重复消费
利刃大大2 小时前
【RabbitMQ】Simple模式 && 工作队列 && 发布/订阅模式 && 路由模式 && 通配符模式 && RPC模式 && 发布确认机制
rpc·消息队列·rabbitmq·队列
J_liaty21 小时前
RabbitMQ面试题终极指南
开发语言·后端·面试·rabbitmq
maozexijr1 天前
RabbitMQ Exchange Headers类型存在的意义?
分布式·rabbitmq
独自破碎E1 天前
RabbitMQ的消息确认机制是怎么工作的?
分布式·rabbitmq
maozexijr1 天前
注解实现rabbitmq消费者和生产者
分布式·rabbitmq
Java 码农2 天前
RabbitMQ集群部署方案及配置指南09
分布式·rabbitmq
论迹2 天前
RabbitMQ
分布式·rabbitmq
Java 码农2 天前
RabbitMQ集群部署方案及配置指南08--电商业务延迟队列定制化方案
大数据·分布式·rabbitmq
Java 码农2 天前
Spring Boot集成RabbitMQ的各种队列使用案例
spring boot·rabbitmq·java-rabbitmq