RabbitMQ高级(一) - 生产者可靠性

生产者重连

这个机制主要用于保证客户端的连接正常。

有时候由于网络波动,可能会出现客户端连接 MQ 失败的情况。通过配置我们可以开启连接失败后的重试机制

配置文件如下:

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

当网络不稳定的时候,利用重试机制可以有效的提高消息发送的成功率。不过 SpringAMQP 提供的重试机制是阻塞式的重试,也就是说多次重试等待的过程中,当前线程是被阻塞的,会影响业务性能。
如果对业务性能有要求,建议禁用 重试机制。如果一定要使用,请合理等待时长和重试次数,当然也可以考虑使用异步线程来执行发送消息的代码。

生产者确认

这个机制主要用于解决发送消息时,失败了怎么办。

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

  • 消息投递到了 MQ,但是路由失败。此时会通过 PublisherReturn 返回路由异常原因,然后返回 ACK ,告知投递成功。
  • 临时消息投递到了 MQ,并且入队成功,返回 ACK,告知投递成功。
  • 持久消息投递到了 MQ,并且入队完成持久化,返回 ACK,告知投递成功。
  • 其他情况都会返回 NACK,告知投递失败。
    使用:
    在配置文件中配置以下信息:
yaml 复制代码
spring:
  rabbitmq:
    publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型
    publisher-returns: true # 开启publisher returns机制,又来返回路由失败的消息

这里publisher-confirm-type有三种模式可以选择:

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

correlated是基于回调机制的,所以我们需要编写回调函数,包括 ReturnsCallback 和 ConfirmCallback

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

java 复制代码
@Slf4j
@Configuration
public class CommonConfig implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 获取 RabbitTemplate 对象
        RabbitTemplate rabbitTemplate = applicationContext.getBean(RabbitTemplate.class);
        // 设置 ReturnsCallback 回调函数
        rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
            @Override
            public void returnedMessage(ReturnedMessage returnedMessage) {
                log.error("消息发送失败:应答码{}", returnedMessage.getReplyCode());
                log.error("消息发送失败:应答信息{}", returnedMessage.getReplyText());
                log.error("消息发送失败:交换机{}", returnedMessage.getExchange());
                log.error("消息发送失败:路由键{}", returnedMessage.getRoutingKey());
                log.error("消息发送失败:消息{}", returnedMessage.getMessage());
            }
        });
    }
}

这只是一个例子,方法不止一种

发送消息,指定消息ID、消息 ConfirmCallback

java 复制代码
public void testconfirm() throws InterruptedException {
    // 创建一个CorrelationData对象,用于关联消息和回调函数,内部会自动创建一个 UUID 用来作为消息的唯一标识
    CorrelationData cd = new CorrelationData();
    // 给correlationData 设置回调函数,当消息发送成功后会调用这个回调函数
    cd.getFuture().whenCompleteAsync((o, throwable) -> {
        if(o.isAck()){
            System.out.println("消息发送成功");
        }else {
            System.out.println("消息发送失败");
            // 重发消息的逻辑
        }
    });
    // 发送消息
    rabbitTemplate.convertAndSend("amq.fanout", "key", "hello",cd);
    // 休眠一下,查看确认消息
    Thread.sleep(1000);
}

总结

  • 生产者确认需要额外的网络和资源开销,尽量不要使用。
  • 如果一定要使用,无需开启 Publisher-Return 机制,因为一般路由失败是自己业务问题。
  • 对于 nack 消息可以有限次数重试,依然失败则记录异常消息。
相关推荐
wdfk_prog2 分钟前
Wi-Fi Direct 教程 05:control socket 与 eloop——P2P_FIND 怎样进入 wpa_supplicant 命令解析器
运维·服务器·后端·网络协议·ubuntu·p2p·wifi-direct
IT_陈寒29 分钟前
Python的GIL锁让我把多线程代码全重写了!
前端·人工智能·后端
马剑威(威哥爱编程)1 小时前
【AI全栈后端12-04】Spring Boot 用结构化输出自动解析简历:让模型按你的 POJO 输出
java·人工智能·spring boot·后端
我的xiaodoujiao2 小时前
Django 基础知识详细图文教程 12-Django 模型定义与使用 2
后端·python·django
孙启超3 小时前
【AI开发之Rust】第 22 课:一键多平台与工程收尾 —— CI、发布检查与结课
开发语言·后端·rust
一条小小yu10 小时前
Spring IoC的理解
java·后端·spring
茉莉玫瑰花茶11 小时前
GO [ 方法 ]
开发语言·后端·golang
Wx-bishekaifayuan11 小时前
django个性化旅游路线推荐平台49005-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
Eric_见嘉11 小时前
在职前端 Skill 和 MCP 分享
前端·后端·agent
孟健13 小时前
出海开发者资金合规:从港卡结汇到完税申报实操
后端·架构