RabbitMQ:生产者可靠性(生产者重连、生产者确认)

目录


一、生产者重连

当网络不稳定的时候,利用重试机制可以有效提高消息发送的成功率。不过SpringAMQP提供的重试机制是阻塞式的重试,也就是说多次重试过程中,当前线程是被阻塞的,会影响业务性能。

如果对于业务性能有要求,建议禁用重试机制。如果一定要使用,请合理配置等待时长和重试次数,当然也可以考虑异步线程来执行发送消息的代码。

yml 复制代码
spring:
	rabbitmq:
	  connection-timeout: 200ms  # 设置连接超时时间
	  template:
	    retry:
	      enabled: true  # 开启超时重试机制
	      initial-interval: 1000ms  # 失败后的初始等待时间
	      multiplier: 1  # 失败后下次的等待时长倍数,下次等待时长=initial-interval * multiplier
	      max-attempts: 3  # 最大重试次数

二、生产者确认

RabbitMQ有两种确认机制:Publisher ConfirmPublisher Return。开启确认机制后,在MQ成功收到消息后会返回确认消息给生产者,返回的结果有以下几种情况:

  1. 消息投递到了MQ,但是路由失败。此时会通过Publisher Return返回路由异常原因,然后返回ACK,告知投递成功。
  2. 临时消息投递给了MQ,并且入队成功,返回ACK,告知投递成功。
  3. 持久消息投递到MQ,并且入队成功,返回ACK,告知投递成功。
  4. 其他情况都会返回NACK,告知投递失败

在生产者服务YML文件中增加一下配置:

yml 复制代码
spring:
  rabbitmq:
    publisher-returns: true  # 开启publisher-return机制
    publisher-confirm-type: correlated  # 设置机制类型:异步

publisher-confirm-type有三种模式可选:

  • none:关闭confirm机制。
  • simple:同步阻塞等待MQ的回执消息。
  • correlated:MQ异步回调方式返回回执消息

每个RabbitTemplate只能配置一个ReturnCallback,因此需要在项目启动过程中配置:

java 复制代码
package com.ming.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class CommonConfig 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) {
                log.error(String.format("ReturnsCallback:消息发送失败,应答码 %s,原因 %s,交换机 %s,路由键 %s,消息 %s ...", returnedMessage.getReplyCode(), returnedMessage.getReplyText(), returnedMessage.getExchange(), returnedMessage.getRoutingKey(), returnedMessage.getMessage()));
            }
        });
    }
}

发送消息,指定消息ID,消息ConfirmCallback,此回调每一次发送消息的时候都要指定:

java 复制代码
@Test
public void confirmCallbackTest() throws InterruptedException {
    // 1. 创建cd
    CorrelationData cd = new CorrelationData();
    // 2. 增加ConfirmCallback
    cd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {
        @Override
        public void onFailure(Throwable throwable) {  // Spring消息回调失败
            log.warn("ConfirmCallback:Spring消息回调失败......", throwable);
        }
        @Override
        public void onSuccess(CorrelationData.Confirm confirm) {  // 消息发送回调
            if (confirm.isAck()) {
                log.info("ConfirmCallback:RabbitMQ 消息发送成功,收到ACK......");
            }else {
                log.warn("ConfirmCallback:RabbitMQ 消息发送成功,收到NACK......", confirm.getReason());
            }
        }
    });
    // 3. 发送消息
    rabbitTemplate.convertAndSend("mt.topic", "china.weather", "黄色警报 ......", cd);  // 成功例子
    // rabbitTemplate.convertAndSend("mt.topic", "aaa", "黄色警报 ......", cd);  // 失败例子
    Thread.sleep(2000);
}
相关推荐
Nyarlathotep01136 小时前
SpringBoot Starter的用法以及原理
java·spring boot
dkbnull1 天前
深入理解Spring两大特性:IoC和AOP
spring boot
初次攀爬者1 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
洋洋技术笔记1 天前
Spring Boot条件注解详解
java·spring boot
洋洋技术笔记2 天前
Spring Boot配置管理最佳实践
spring boot
用户8307196840823 天前
Spring Boot 项目中日期处理的最佳实践
java·spring boot
大道至简Edward3 天前
Spring Boot 2.7 + JDK 8 升级到 Spring Boot 3.x + JDK 17 完整指南
spring boot·后端
洋洋技术笔记3 天前
Spring Boot启动流程解析
spring boot·后端
怒放吧德德4 天前
Spring Boot 实战:RSA+AES 接口全链路加解密(防篡改 / 防重放)
java·spring boot·后端
李慕婉学姐4 天前
Springboot智慧社区系统设计与开发6n99s526(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。
数据库·spring boot·后端