RabbitMQ-生产者可靠性

一、生产者重连

1、概念

由于网络波动导致客户端无法连接上MQ,这是可以开启MQ的失败后重连机制。

注意:

是连接失败的重试,而不是消息发送失败后的重试。

2、开启配置

XML 复制代码
spring:
  rabbitmq:
    template:
      retry:
        enabled: true # 是否启用重试机制
        max-attempts: 3 # 最大重试次数
        initial-interval: 1000ms # 第一次重试的间隔时间
        multiplier: 2 # 重试间隔时间的倍数
        max-interval: 10000ms # 最大重试间隔时间,超过该时间则停止重试

3、重连结果

4、总结

这种超时重连的方式是阻塞式的,后面的代码没办法执行,如果说业务要求比较严格,则需要禁止使用;如果必要使用的情况下,合理设置重连时间。

二、生产者确认

1、概念

生产者将消息发送到MQ之后,MQ会返回一个确认消息给到生产者。有两种方式:

  • Publisher Confirm 消息确认
  • Publisher Return 消息回执

有几种情况产生:

  • 消息投递到MQ,但是路由失败。Publisher Return会返回路由失败,然后返回ACK,告知投递成功。
  • 临时消息投递到MQ,并且入队成功。返回ACK,告知投递成功。
  • 持久消息投递到MQ,并且持久化完成。返回ACK,告知投递成功。
  • 除上述情况外,均会返回NACK,告知投递失败。

2、开启配置

java 复制代码
spring:
  rabbitmq:
    publisher-confirm-type: correlated # 消息确认机制,异步确认
    publisher-returns: true # 消息返回机制

其中,publisher-confirm-type有三种模式:

  • none:不开启确认机制。
  • simple:同步阻塞等待MQ的回执消息,生产者同步等待。
  • correlated:MQ异步回调方式返回回执消息,生产者发送消息之后,继续执行其他任务,MQ收到消息之后,处理完会回执确认信息。首选

3、代码实现

Publisher Return的配置类,这个只需要写一个就行了,但是Publisher Confirm是每次一个消息发送的时候都得写一个:

java 复制代码
@Configuration
public class MqConfirmConfig implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        //获取模板类
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
        //创建回调
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                System.out.println("消息返回-----开始");
                System.out.println(returnedMessage.getReplyCode());
                System.out.println(returnedMessage.getExchange());
                System.out.println(returnedMessage.getReplyText());
                System.out.println(returnedMessage.getRoutingKey());
                System.out.println("消息返回-----结束");
            }
        });
    }
}

Publisher Confirm例子:

java 复制代码
public String push9() throws InterruptedException {
        //1、创建CorrelationData,
        // 构造函数需要指定随机id,消息回调时需要使用该id进行匹配
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        //2、添加ConfirmCallback
        correlationData.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
            //这个一般不会触发
            @Override
            public void onFailure(Throwable ex) {
                System.out.println("消息回调失败");
            }

            @Override
            public void onSuccess(CorrelationData.Confirm result) {
                //交换机收到消息,不管路由是否成功都会收到
                if (result.isAck()) {
                    System.out.println("消息确认成功");
                } else {
                    //交换机错误或者网络错误就会重试
                    System.out.println("消息确认失败,失败原因为:" + result.getReason());
                }
            }
        });

        String topicExchange = "topicExchange";
        rabbitTemplate.convertAndSend(topicExchange, "cq.hh","重庆串串也好吃",correlationData);
        Thread.sleep(4000);
        return "success";
    }

rabbitTemplate.convertAndSend(topicExchange, "cq.hh","重庆串串也好吃",correlationData); 加粗的这个绑定不要忘记了,我就是忘记了这个,一直找不到原因。

4、结果测试

(1)如果是交换机写错了,就说明交换机没有收到消息,所以ACK应答是false:

(2)交换机收到消息,路由失败;会显示交换机收到消息了,ACK成功,但是Publisher Return会告诉你相关信息,比如没有路由:NO_ROUTE

(3)消息接收成功,路由成功的场景,直接告诉ACK成功:

相关推荐
茶杯梦轩6 天前
从零起步学习RabbitMQ || 第三章:RabbitMQ的生产者、Broker、消费者如何保证消息不丢失(可靠性)详解
分布式·后端·面试
回家路上绕了弯8 天前
深入解析Agent Subagent架构:原理、协同逻辑与实战落地指南
分布式·后端
用户8307196840828 天前
Spring Boot 集成 RabbitMQ :8 个最佳实践,杜绝消息丢失与队列阻塞
spring boot·后端·rabbitmq
用户83071968408210 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者11 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者13 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧14 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖14 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农14 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者14 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端