四种战略确保 RabbitMQ 消息发送可靠性!你用哪种?

[复制链接]
发表于 2026-2-12 23:43:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
如果能确认这两步,那么我们就可以以为消息发送乐成了。
如果这两步中任一步调出现标题,那么消息就没有乐成送达,此时我们大概要通过重试等方式去重新发送消息,多次重试之后,如果消息照旧不能到达,则大概就须要人工参与了。
颠末上面的分析,我们可以确认,要确保消息乐成发送,我们只须要做好三件事就可以了:

  • 确认消息到达 Exchange。
  • 确认消息到达 Queue。
  • 开启定时任务,定时投递那些发送失败的消息。
2. RabbitMQ 的积极

上面提出的三个步调,第三步须要我们自己实现,前两步 RabbitMQ 则有现成的办理方案。
怎样确保消息乐成到达 RabbitMQ?RabbitMQ 给出了两种方案:

  • 开启变乱机制
  • 发送方确认机制
这是两种差异的方案,不可以同时开启,只能选择此中之一,如果两者同时开启,则会报如下错误:

我们分别来看。以下全部案例都在 Spring Boot 中睁开,文末可以下载相干源码。
2.1 开启变乱机制

Spring Boot 中开启 RabbitMQ 变乱机制的方式如下:
起首须要先提供一个变乱管理器,如下:
@Bean
RabbitTransactionManager transactionManager(ConnectionFactory connectionFactory) {
return new RabbitTransactionManager(connectionFactory);
}
接下来,在消息生产者上面做两件事:添加变乱注解并设置通讯信道为变乱模式:
@Service
public class MsgService {
@Autowired
RabbitTemplate rabbitTemplate;
@Transactional
public void send() {
rabbitTemplate.setChannelTransacted(true);
rabbitTemplate.convertAndSend(RabbitConfig.JAVABOY_EXCHANGE_NAME,RabbitConfig.JAVABOY_QUEUE_NAME,“hello rabbitmq!”.getBytes());
int i = 1 / 0;
}
}
这里注意两点:

  • 发送消息的方法上添加 @Transactional 注解标记变乱。
  • 调用 setChannelTransacted 方法设置为 true 开启变乱模式。
这就 OK 了。
在上面的案例中,我们在末端来了个 1/0 ,这在运行时一定抛出非常,我们可以实行运行该方法,发现消息并未发送乐成。
当我们开启变乱模式之后,RabbitMQ 生产者发送消息会多出四个步调:

  • 客户端发出哀求,将信道设置为变乱模式。
  • 服务端给出复兴,同意将信道设置为变乱模式。
  • 客户端发送消息。
  • 客户端提交变乱。
  • 服务端给出相应,确认变乱提交。
上面的步调,除了第三步是原来就有的,其他几个步调都是平白无端多出来的。以是各人看到,变乱模式着实服从有点低,这并非一个最佳办理方案。我们可以想想,什么项目会用到消息中心件?一样平常来说都是一些高并发的项目,这个时间并发性能尤为告急。
以是,RabbitMQ 还提供了发送方确认机制(publisher confirm)来确保消息发送乐成,这种方式,性能要远远高于变乱模式,一起来看下。
2.2 发送方确认机制

2.2.1 单条消息处置惩罚

起首我们移除刚刚关于变乱的代码,然后在 application.properties 中设置开启消息发送方确认机制,如下:
spring.rabbitmq.publisher-confirm-type=correlated
spring.rabbitmq.publisher-returns=true
第一行是设置消息到达互换器简直认回调,第二行则是设置消息到达队列的回调。
第一行属性的设置有三个取值:

  • none:体现禁用发布确认模式,默认即此。
  • correlated:体现乐成发布消息到互换器后会触发的回调方法。
  • simple:类似 correlated,而且支持 waitForConfirms() 和 waitForConfirmsOrDie() 方法的调用。
接下来我们要开启两个监听,详细设置如下:
@Configuration
public class RabbitConfig implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {
public static final String JAVABOY_EXCHANGE_NAME = “javaboy_exchange_name”;
public static final String JAVABOY_QUEUE_NAME = “javaboy_queue_name”;
private static final Logger logger = LoggerFactory.getLogger(RabbitConfig.class);
@Autowired
RabbitTemplate rabbitTemplate;
@Bean
Queue queue() {
return new Queue(JAVABOY_QUEUE_NAME);
}
@Bean
DirectExchange directExchange() {
return new DirectExchange(JAVABOY_EXCHANGE_NAME);
}
@Bean
Binding binding() {
return BindingBuilder.bind(queue())
.to(directExchange())
.with(JAVABOY_QUEUE_NAME);
}
@PostConstruct
public void initRabbitTemplate() {
rabbitTemplate.setConfirmCallback(this);
rabbitTemplate.setReturnsCallback(this);
}
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
logger.info(“{}:消息乐成到达互换器”,correlationData.getId());
}else{
logger.error(“{}:消息发送失败”, correlationData.getId());
}
}
@Override
public void returnedMessage(ReturnedMessage returned) {
logger.error(“{}:消息未乐成路由到队列”,returned.getMessage().getMessageProperties().getMessageId());
}
}
关于这个设置类,我说如下几点:

  • 界说设置类,实现 RabbitTemplate.ConfirmCallback 和 RabbitTemplate.ReturnsCallback 两个接口,这两个接口,前者的回调用来确定消息到达互换器,后者则会在消息路由到队列失败时被调用。
  • 界说 initRabbitTemplate 方法并添加 @PostConstruct 注解,在该方法中为 rabbitTemplate 分别设置这两个 Callback。
这就可以了。
接下来我们对消息发送举行测试。
起首我们实行将消息发送到一个不存在的互换机中,像下面如许:
rabbitTemplate.convertAndSend(“RabbitConfig.JAVABOY_EXCHANGE_NAME”,RabbitConfig.JAVABOY_QUEUE_NAME,“hello rabbitmq!”.getBytes(),new CorrelationData(UUID.randomUUID().toString()));
注意第一个参数是一个字符串,不是变量,这个互换器并不存在,此时控制台会报如下错误:

接下来我们给定一个真实存在的互换器,但是给一个不存在的队列,像下面如许:
rabbitTemplate.convertAndSend(RabbitConfig.JAVABOY_EXCHANGE_NAME,“RabbitConfig.JAVABOY_QUEUE_NAME”,“hello rabbitmq!”.getBytes(),new CorrelationData(UUID.randomUUID().toString()));
自我先容一下,小编13年上海交大结业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里不绝到现在。
深知大多数Java工程师,想要提升技能,每每是自己探索发展大概是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学结果低效又漫长,而且极易遇到天花板技能故步自封!
因此网络整理了一份《2024年Java开发全套学习资料》,初志也很简朴,就是盼望可以大概资助到想自学提升又不知道该从何学起的朋侪,同时减轻各人的负担。



既有恰当小白学习的零底子资料,也有恰当3年以上履历的小搭档深入学习提升的进阶课程,根本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比力大,这里只是将部分目次截图出来,每个节点内里都包罗大厂面经、学习条记、源码课本、实战项目、讲授视频,而且会一连更新!
如果你以为这些内容对你有资助,可以扫码获取!!(备注Java获取)
分享

起首分享一份学习大纲,内容较多,涵盖了互联网行业全部的盛行以及核心技能,以截图情势分享:
(亿级流量性能调优实战+一线大厂分布式实战+架构师筑基必备技能+操持头脑开源框架解读+性能直线提升架构技能+高效存储让项目性能腾飞+分布式扩展到微服务架构…着实是太多了)
其次分享一些技能知识,以截图情势分享一部分:
Tomcat架构分析:

算法练习+高分宝典:

Spring Cloud+Docker微服务实战:

末了分享一波口试资料:
   切莫死记硬背,鉴戒口试官直接让你出门右拐
  1000道互联网Java口试题:

Java高级架构口试知识整理:

《互联网大厂口试真题分析、进阶开发核心学习条记、全套讲授视频、实战项目源码课本》点击传送门即可获取!
.(img-rfvnSyXC-1712891443505)]
Spring Cloud+Docker微服务实战:
[外链图片转存中…(img-XjvYmQh7-1712891443505)]
末了分享一波口试资料:
   切莫死记硬背,鉴戒口试官直接让你出门右拐
  1000道互联网Java口试题:
[外链图片转存中…(img-JABdsDzm-1712891443505)]
Java高级架构口试知识整理:
[外链图片转存中…(img-dLddRbhC-1712891443506)]
《互联网大厂口试真题分析、进阶开发核心学习条记、全套讲授视频、实战项目源码课本》点击传送门即可获取!
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表