RabbitMQ高级特性----生产者确认机制

ops/2025/2/28 10:46:01/

题记:在Java微服务开发中,对于一个功能需要调用另一个服务下的功能才能实现的情况,我们通常会使用异步调用取代同步调用,进而实现增强业务的可拓展性和实现故障隔离以及流量削峰填谷的目的。而消息队列就是异步调用的解决方案之一。不过在使用消息队列实现异步调用的时候,可能会出现消息无法传递到位进而导致业务信息出现差异的情况,因此消息的传递的可靠性就显得尤为重要。

传递消息的流程:

要保障消息传递的可靠性,我们可以从消息队列的每一步分析,以RabbitMQ为例,其发送消息的流程大致如下图所示:

不难发现消息传递一共会经历三名角色,分别是消息发送者,MQ和消息接收者。因此我们要保证消息成功传递并被正确处理就需要保证这三者的可靠性。

发送者可靠性:

1.1生产者重连

首先第一种情况,就是生产者发送消息时,出现了网络故障,导致与MQ的连接中断。为了解决这个问题,SpringAMQP提供的消息发送时的重试机制。即:当RabbitTemplate与MQ连接超时后,多次重试。

我们可以在消息发送者的yml配置文件中加入如下信息:

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

我们可以在消息发送者工程下创建一个Test模拟向rabbitMQ发送消息(在此之前我们需要把rabbiitMQ关闭或是断掉网络)

    @Testpublic void TestTimeOutPublish(){rabbitTemplate.convertAndSend("simple.queue","Hello,world");}

代码执行后会是这样的效果:

通过日志我们可以观察到一共重连了三次,与我们在yml文件中配置的max-attempt属性一致。需要注意的是,这里等待的时间还需要再加上connect-timeout这一判定连接超时的配置。

1.2生产者确认机制

在保证网络畅通并且RabbitMQ服务正确启动了的前提下,我们就可以成功将消息发送到MQ中了。

不过仍有少数情况下会出现消息进入mq后丢失的情况:

  • 无法找到指定的exchange,大部分情况下就是交换机名称出错
  • exchange无法正确路由到queue,可能是routeKey错误导致的

针对上述情况,RabbitMQ提供了生产者消息确认机制,包括Publisher ConfirmPublisher Return两种。在开启确认机制的情况下,当生产者发送消息给MQ后,MQ会根据消息处理的情况返回不同的回执

当我们在yml文件中增加了相应的配置后流程就变得如下图所示:

配置完成之后:

  • 对于所有成功投递如Mq中的消息都会返回Ack,表示投递成功。
  • 对于投递成功但路由失败的消息,会返回Publish Return并返回Ack
  • 除此之外的所有消息都返回NAck,表示消息投递失败

需要注意的是,对于临时消息而言是进入队列Publisher Comfirm就是返回Ack,如果是持久消息则需要写入磁盘后才是返回Ack。

实现方式如下:

publisher消息发送者yml配置文件中加入:

spring:rabbitmq:publisher-confirm-type: correlated # 开启publisher confirm机制,并设置confirm类型publisher-returns: true # 开启publisher return机制

pubulisher-confirm-type一共有三种属性提供选择:

  1. none:默认选项,关闭
  2. correlated:异步回调返回回执
  3. simple:同步阻塞等待mq回执

并且我们还需要在配置类中配置confrim Return报文:

public class MqConfig {private final RabbitTemplate rabbitTemplate;@PostConstruct  //在注入rabbitTemplate依赖后执行public void init(){rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {@Overridepublic void returnedMessage(ReturnedMessage returned) {log.error("触发return callback,");log.debug("exchange: {}", returned.getExchange());log.debug("routingKey: {}", returned.getRoutingKey());log.debug("message: {}", returned.getMessage());log.debug("replyCode: {}", returned.getReplyCode());log.debug("replyText: {}", returned.getReplyText());}});}
}

对于不同的业务我们有不同的处理方案,因此CallbackComfirm需要在每次发送方法前定义,并且由作为convertMessage方法的参数,如下所示:

@Test
void testPublisherConfirm() {// 1.创建CorrelationDataCorrelationData cd = new CorrelationData();// 2.给Future添加ConfirmCallbackcd.getFuture().addCallback(new ListenableFutureCallback<CorrelationData.Confirm>() {@Overridepublic void onFailure(Throwable ex) {// 2.1.Future发生异常时的处理逻辑,基本不会触发log.error("send message fail", ex);}@Overridepublic void onSuccess(CorrelationData.Confirm result) {// 2.2.Future接收到回执的处理逻辑,参数中的result就是回执内容if(result.isAck()){ // result.isAck(),boolean类型,true代表ack回执,false 代表 nack回执log.debug("发送消息成功,收到 ack!");}else{ // result.getReason(),String类型,返回nack时的异常描述log.error("发送消息失败,收到 nack, reason : {}", result.getReason());}}});// 3.发送消息rabbitTemplate.convertAndSend("simple.direct", "simple", "hello,RabbiteMQ", cd);
}

我们可以在onSuccess和onFailure中编写我们对这一消息发送成功以及失败情况的对应处理。

如果关于上述有其他更好的建议以及疑问,欢迎留言,我将尽快回复。


http://www.ppmy.cn/ops/161935.html

相关文章

基于大数据的音乐网站数据分析与可视化推荐系统

【大数据】基于大数据的音乐网站数据分析与可视化推荐系统&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 本选题旨在设计并实现一款基于大数据技术的音乐网站数据分析与可视化推荐系统&#x…

linux在vim中查找和替换

在Linux中使用Vim编辑器查找文本的方法非常直观和强大。Vim是一个高度可配置的文本编辑器&#xff0c;支持多种查找和替换的命令。下面是一些基本的查找命令&#xff1a; 1. 向前查找 要向前查找文本&#xff0c;可以使用以下命令&#xff1a; /text_to_find 例如&#xff0c…

[数字排列]

数字排列 真题目录: 点击去查看 E 卷 100分题型 题目描述 小明负责公司年会,想出一个趣味游戏: 屏幕给出 1 ~ 9 中任意 4 个不重复的数字,大家以最快时间给出这几个数字可拼成的数字从小到大排列位于第 N 位置的数字,其中 N 为给出数字中最大的(如果不到这么多数字则给…

3D技术在文博行业的革新应用有哪些?

在当今社会&#xff0c;看展览已成为国人精神生活的重要组成部分&#xff0c;而“云游博物馆”作为一种新兴趋势&#xff0c;正以前所未有的速度席卷文化领域。众多博物馆紧跟时代步伐&#xff0c;利用多样化的手段&#xff0c;让文化传播更加贴近大众生活。其中&#xff0c;3D…

Linux——高级IO(select后续poll,epoll)

目录 一、poll函数 1.函数原型 2.参数说明 3.struct pollfd 结构体 4.返回值 5.使用步骤 6.与 select 的对比 7.适用场景 8.缺点 9.总结 二、epoll函数 1.核心思想 2.核心函数 1. epoll_create - 创建 epoll 实例 2. epoll_ctl - 管理 epoll 事件表 3. epoll_w…

【 树 】

【树 】 目录1. 二叉搜索树&#xff08;BST&#xff09;的退化知识点示例 2. 平衡树的定义3. AVL 树知识点不平衡产生的原因旋转操作 4. AVL 树代码设计树节点旋转操作插入节点操作删除节点操作测试代码 红黑树的定义代码设计节点类设计左旋和右旋操作 插入操作删除操作黑侄情形…

【Python实战】——Python+Opencv是实现车牌自动识别

&#x1f349;CSDN小墨&晓末:https://blog.csdn.net/jd1813346972 个人介绍: 研一&#xff5c;统计学&#xff5c;干货分享          擅长Python、Matlab、R等主流编程软件          累计十余项国家级比赛奖项&#xff0c;参与研究经费10w、40w级横向 文…

tableau之网络图和弧线图

一、网络图 概念 网络图&#xff08;Network Graph&#xff09;&#xff0c;也称为网络可视化&#xff0c;是数据可视化的一种形式&#xff0c;用于显示实体&#xff08;节点&#xff09;之间的关系&#xff08;边&#xff09;。这种图表通过节点和边的结构揭示数据中的复杂关…