Rabbitmq可靠消息投递,消息确认机制
前言
我们知道,消息从发送到签收的整个过程是
Producer-->Broker/Exchange-->Broker/Queue-->Consumer
,因此如果只是要保证消息的可靠投递,我们需要考虑的仅是前两个阶段,因为消息只要成功到达队列,就算投递成功。
- 比如投递消息时指定的Exchange不存在,那么阶段一就会失败
- 如果投递到Exchange成功,但是指定的路由件错误或者别的原因,消息没有从Exchange到达Queue,那就是第二阶段出错。
而从生产者和消费者角度来看,消息成功投递到队列才算成功投递,因此阶段一和阶段而都属于生产者一方需要关注,阶段三属于消费者一方,这里只考虑消息的成功投递,因此不考虑消费者的签收部分。而Rabbitmq和springboot整合时,默认是没有开启消息确认的。
开启消息确认机制
一、Producer --> Broker/Exchange ConfirmCallback
1. 配置
# springboot2.2.0以前,
# spring.rabbitmq.publisher-confirms=true
# springboot2.2.0以后
spring.rabbitmq.publisher-confirm-type=correlated
关于这个Type有三种取值:
none
:默认值,不开启confirmcallback机制correlated
:开启confirmcallback,发布消息时,可以指定一个CorrelationData,会被保存到消息头中,消息投递到Broekr时触发生产者指定的ConfirmCallback,这个值也会被返回,以进行对照处理,CorrelationData可以包含比较丰富的元信息进行回调逻辑的处理。无特殊需求,就设定为这个值。simple
:这个比较复杂,spring官方指出:Normally, when using the template, a Channel is checked out of the cache (or created), used for the operation, and returned to the cache for reuse. In a multi-threaded environment, there is no guarantee that the next operation uses the same channel. There may be times, however, where you want to have more control over the use of a channel and ensure that a number of operations are all performed on the same channel.
2529 / 5000
翻译结果
通常,使用模板时,会从缓存中检出(或创建)通道,以进行操作,然后将其返回到缓存中以进行重用。在多线程环境中,不能保证下一个操作使用相同的通道。但是,有时您可能希望更好地控制通道的使用,并确保在同一通道上执行全部操作。也就说这,这个
simple
模式:其一效果和correlated
值一样能触发回调方法,其二用于发布消息成功后使用rabbitTemplate调用waitForConfirms
或waitForConfirmsOrDie
方法等待broker
节点返回发送结果,需求根据返回结果来判定下一步的逻辑,执行更复杂的业务。要注意的点是waitForConfirmsOrDie
方法如果返回false则会关闭channel
,则接下来无法发送消息。
2. 如何使用
SpringBoot
自动配置帮我们往容器中注册了一个RabbitTemplate
,但因为默认没有开启消息确认机制,因此它在创建时并未配置confirmCallback
属性,我们需要手动为其创建一个 RabbitTemplate.ConfirmCallback
。
因此我们需要拿到这个创建好的RabbitTemplate
,再手动执行其setConfirmCallback
方法。
拿到这个对象简单,只要一个@Autowired
,问题是我们要保证之后通过@Autowired
拿到的RabbitTemplate
是已经注册了ConfirmCallback
的。
我们手写一个配置类/或者随便什么类,加上注解@Component/@Service/@Controller/@Configuration
,无论哪个,只要能被自动创建并加入容器,然后我们写一个方法,加上@PostConstructor
表示创建这个对象完成时需要回调这个方法,我们在这个类中拿到RabbitTemplate
,在这个方法中执行它的setConfirmCallback
,这样spring容器在创建我们这个配置类的时候将创好的RabbitTemplate
进行了完善,而整个过程都是在spring'boot启动过程中自动完成,就能保证我们之后使用@Autowired
拿到的RabbitTemplate
就是注册号confirmCallback
的。
@Configuration
@Slf4j
public class RabbitConfig {
@Autowired
RabbitTemplate rabbitTemplate;
// 方法名无所谓,主要是 @PostConstruct 指定它一定会被回调
@PostConstruct
public void setCallback() {
/**
* 为容器创建好的rabbitTemplate注册confirmCallback
* 消息由生产者投递到Broker/Exchange回调
*/
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
/**
* @param correlationData 发送消息时指定的唯一关联数据(消息id)
* @param ack 这个消息是否成功投递到Exchange
* @param cause 失败的原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
log.info("消息投递到交换机成功:[correlationData={}]",correlationData);
} else {
log.error("消息投递到交换机失败:[correlationData={},原因:{}]", correlationData, cause);
}
}
});
}
}
二、Exchange-->Queue ConfirmCallback
1. 配置
- 注意下面两项必须同时配置,可以尝试不配置第二项,通过测试能够发现当消息路由到Queue失败(比如路由件错误)时,returnCallback并未被回调。
# 开启阶段二(消息从E->Q)的确认回调 Exchange --> Queue returnCallback
spring.rabbitmq.publisher-returns=true
# 官方文档说此时这一项必须设置为true
# 实际上这一项的作用是:消息【未成功到达】队列时,能监听到到路由不可达的消息,以异步方式优先调用我们自己设置的returnCallback,默认情况下,这个消息会被直接丢弃,无法监听到
spring.rabbitmq.template.mandatory=true
2. 如何使用
和注册confirmCallback的原理一样,就不多赘述,直接看配置,需要注意的是 这个回调只会在消息在从Exchange投递到Queue【失败】时被执行。
@Configuration
@Slf4j
public class RabbitConfig {
@Autowired
RabbitTemplate rabbitTemplate;
@PostConstruct
public void setCallback() {
rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
/**
* 能够看出来,参数中并没有像confirmCallback那样提供的boolean类型 的ack,因此这个回调只是在【失败】情况下触发的
* @param message 发送的消息
* @param replyCode 回复错误码
* @param replyText 回复错误内容
* @param exchange 发送消息时指定的交换机
* @param routingKey 发送消息时使用的路由件
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
log.error("路由到队列失败,消息内容:{},交换机:{},路由件:{},回复码:{},回复文本:{}", message, exchange, routingKey, replyCode, replyText);
}
});
}
}
Rabbitmq可靠消息投递,消息确认机制的更多相关文章
- rabbitmq 不发送ack消息如何处理:rabbitmq可靠发送的自动重试机制
转载地址:http://www.jianshu.com/p/6579e48d18ae http://www.jianshu.com/p/4112d78a8753 接这篇 在上文中,主要实现了可靠模式的 ...
- springboot项目整合rabbitMq涉及消息的发送确认,消息的消费确认机制,延时队列的实现
1.引入maven依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactI ...
- [转载]rabbitmq可靠发送的自动重试机制
转载地址http://www.jianshu.com/p/6579e48d18ae http://www.jianshu.com/p/4112d78a8753 接这篇 在上文中,主要实现了可靠模式的c ...
- RabbitMQ 消息确认机制
消息确认机制 在之前异常处理部分就已经写了,对于consumer的异常退出导致消息丢失,可以时候consumer的消息确认机制.重复的就不说了,这里说一些不一样的. consumer的消息确认机制 当 ...
- RabbitMQ消息队列(六)-消息任务分发与消息ACK确认机制(.Net Core版)
在前面一章介绍了在.Net Core中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消费者消费同一个队列怎么办?如果这几个消费者分任务的权重不同怎么办?怎么把 ...
- SpringBoot 整合 RabbitMQ(包含三种消息确认机制以及消费端限流)
目录 说明 生产端 消费端 说明 本文 SpringBoot 与 RabbitMQ 进行整合的时候,包含了三种消息的确认模式,如果查询详细的确认模式设置,请阅读:RabbitMQ的三种消息确认模式 同 ...
- (六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版)
原文:(六)RabbitMQ消息队列-消息任务分发与消息ACK确认机制(PHP版) 在前面一章介绍了在PHP中如何使用RabbitMQ,至此入门的的部分就完成了,我们内心中一定还有很多疑问:如果多个消 ...
- 【RabbitMQ】如何进行消息可靠投递【上篇】
说明 前几天,突然发生线上报警,钉钉连发了好几条消息,一看是RabbitMQ相关的消息,心头一紧,难道翻车了? [橙色报警] 应用[xxx]在[08-15 16:36:04]发生[错误日志异常],al ...
- 【RabbitMQ】如何进行消息可靠投递【下篇】
说明 上一篇文章里,我们了解了如何保证消息被可靠投递到RabbitMQ的交换机中,但还有一些不完美的地方,试想一下,如果向RabbitMQ服务器发送一条消息,服务器确实也接收到了这条消息,于是给你返回 ...
随机推荐
- Linux下weblogic启动慢
修改Linux上Weblogic使用的jdk $JAVA_HOME/jre/lib/security/java.security (/bea/weblogic/jdk150_12/jre/lib/se ...
- Mybatis执行流程源码分析
第一部分:项目结构 user_info表:只有id和username两个字段 User实体类: public class User { private String username; private ...
- 使用 vue 仿写的一个购物商城
在学习了 vue 之后,决定做一个小练习,仿写了一个有关购物商城的小项目.下面就对项目做一个简单的介绍. 项目源码: github 项目的目录结构 -assets 与项目有关的静态资源,包括 css, ...
- 使用php进行微信小程序图片安全验证
想用到微信公众平台的图片识别系统,结果报错{"errcode":41005,"errmsg":"media data missing hint: [x ...
- JMeter上传文件,并修改源码参数化Content-Disposition 的 filename
一.JMeter上传文件 1.使用F12或抓包工具抓包对应接口 如下图为一个上传图片接口,抓包显示内容如下: 2.将抓包到的信息头内容填写到jmeter的HTTP信息头管理器 3.填写参数 由抓包的接 ...
- 为什么放弃Hibernate、JPA、Mybatis,最终选择JDBCTemplate
一.前言 因为项目需要选择数据持久化框架,看了一下主要几个流行的和不流行的框架,对于复杂业务系统,最终的结论是,JOOQ是总体上最好的,可惜不是完全免费,最终选择JDBC Template. Hibe ...
- Arduino PROGMEM 从程序空间读取float值的方法
方法: 使用avr-libc提供的宏定义: #define pgm_read_float_near(address_short) __LPM_float((uint16_t)(address_shor ...
- js中点回车enter触发事件&layui弹窗按enter键不停弹窗问题的解决&js实现鼠标焦点自动落到文本框(layui)
js中回车触发事件 一. document.onkeydown = function (e) { // 回车提交表单 // 兼容FF和IE和Opera var theEvent = window.e ...
- 磁盘配额,通过ManagementClass("Win32_DiskQuota")
C# using System; using System.Collections.Generic; using System.Management; namespace ConsoleApp2 { ...
- 私有Maven仓库安装和使用
安装 这里选择安装的是windows平台,linux安装类似,下载可能要梯子 官网下载页 https://help.sonatype.com/repomanager2/download 下载链接 ht ...