SpringBoot+RabbitMQ 死信队列
点击上方“码农突围”,马上关注
这里是码农充电第一站,回复“666”,获取一份专属大礼包
真爱,请设置“星标”或点个“在看
前言
死信:无法被消费的消息,称为死信。
如果死信一直留在队列中,会导致一直被消费,却从不消费成功。
所以我们专门开辟了一个来存放死信的队列,叫死信队列(DLX,dead-letter-exchange
)。
死信的几种来源:
消息 TTL 过期(time to live,存活时间,可以用在限时支付消息)
队列达到最大长度(队列满了,无法路由到该队列)
消息被拒绝(
basic.reject / basic.nack
),并且requeue = false
环境准备配置
准备 MQ 的队列和环境:
正常交换机
正常队列(最长队列 5) ---- 正常消费者,拒绝消息
ttl 队列(过期时间 60 秒) ---- 没有消费者
死信交换机
死信队列
主要配置文件如下:
@Configuration
public class DeadConfig {/* 正常配置 **********************************************************************************************************//*** 正常交换机,开启持久化*/@BeanDirectExchange normalExchange() {return new DirectExchange("normalExchange", true, false);}@Beanpublic Queue normalQueue() {// durable: 是否持久化,默认是false,持久化队列:会被存储在磁盘上,当消息代理重启时仍然存在,暂存队列:当前连接有效// exclusive: 默认也是false,只能被当前创建的连接使用,而且当连接关闭后队列即被删除。此参考优先级高于durable// autoDelete: 是否自动删除,当没有生产者或者消费者使用此队列,该队列会自动删除。Map<String, Object> args = deadQueueArgs();// 队列设置最大长度args.put("x-max-length", 5);return new Queue("normalQueue", true, false, false, args);}@Beanpublic Queue ttlQueue() {Map<String, Object> args = deadQueueArgs();// 队列设置消息过期时间 60 秒args.put("x-message-ttl", 60 * 1000);return new Queue("ttlQueue", true, false, false, args);}@BeanBinding normalRouteBinding() {return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("normalRouting");}@BeanBinding ttlRouteBinding() {return BindingBuilder.bind(ttlQueue()).to(normalExchange()).with("ttlRouting");}/* 死信配置 **********************************************************************************************************//*** 死信交换机*/@BeanDirectExchange deadExchange() {return new DirectExchange("deadExchange", true, false);}/*** 死信队列*/@Beanpublic Queue deadQueue() {return new Queue("deadQueue", true, false, false);}@BeanBinding deadRouteBinding() {return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("deadRouting");}/*** 转发到 死信队列,配置参数*/private Map<String, Object> deadQueueArgs() {Map<String, Object> map = new HashMap<>();// 绑定该队列到私信交换机map.put("x-dead-letter-exchange", "deadExchange");map.put("x-dead-letter-routing-key", "deadRouting");return map;}}
arguments 具体参数如下:
队列达到最大长度
首先测试最简单的,没有消费者。
调用6次正常队列的生产方法。
/*** 正常消息队列,队列最大长度5*/@GetMapping("/normalQueue")public String normalQueue() {Map<String, Object> map = new HashMap<>();map.put("messageId", String.valueOf(UUID.randomUUID()));map.put("data", System.currentTimeMillis() + ", 正常队列消息,最大长度 5");rabbitTemplate.convertAndSend("normalExchange", "normalRouting", map, new CorrelationData());return JSONObject.toJSONString(map);}
MQ 结果如下:
消息 TTL 过期
消息的TTL 指的是消息的存活时间,我们可以通过设置消息的TTL或者队列的TTL来实现。
消息的TTL :对于设置了过期时间属性(expiration)的消息,消息如果在过期时间内没被消费,会过期
队列的TTL :对于设置了过期时间属性(x-message-ttl)的队列,所有路由到这个队列的消息,都会设置上这个过期时间
两种配置都行,一般都用在定时任务,限时支付这种地方。
/*** 消息 TTL, time to live*/@GetMapping("/ttlToDead")public String ttlToDead() {Map<String, Object> map = new HashMap<>();map.put("messageId", String.valueOf(UUID.randomUUID()));map.put("data", System.currentTimeMillis() + ", ttl队列消息");rabbitTemplate.convertAndSend("normalExchange", "ttlRouting", map, new CorrelationData());return JSONObject.toJSONString(map);}
发送后:
等待过期后:
Demo 中只是为了方便,代码中尽量使用 消息TTL,不要用 队列TTL
拒绝消息
正常队列消费后拒绝消息,并且不进行重新入队:
@Component
@RabbitListener(queues = "normalQueue")
public class NormalConsumer {@RabbitHandlerpublic void process(Map<String, Object> message, Channel channel, Message mqMsg) throws IOException {System.out.println("收到消息,并拒绝重新入队 : " + message.toString());channel.basicReject(mqMsg.getMessageProperties().getDeliveryTag(), false);}
}
MQ 控制台:
死信队列消费:
@Component
@RabbitListener(queues = "deadQueue")
public class DeadConsumer {@RabbitHandlerpublic void process(Map<String, Object> message, Channel channel, Message mqMsg) throws IOException {System.out.println("死信队列收到消息 : " + message.toString());channel.basicAck(mqMsg.getMessageProperties().getDeliveryTag(), false);}
}
消息顺序和实验一致:
死信队列收到消息 : {data=1631534291765, 正常队列消息,最大长度 5, messageId=bce3888b-da38-4299-ac88-d22cbe164739}
死信队列收到消息 : {data=1631535222745, ttl队列消息, messageId=a4617445-5aab-4fac-aec7-5709ea699598}
死信队列收到消息 : {data=1631534503765, 正常队列消息,最大长度 5, messageId=b65ecaab-5ce7-4597-a32c-c90b67ec46da}
死信队列收到消息 : {data=1631534511468, 正常队列消息,最大长度 5, messageId=d63d2a4c-e7d3-4f00-a6ca-78e2d62d1d92}
死信队列收到消息 : {data=1631534585087, 正常队列消息,最大长度 5, messageId=eed0c349-415b-43dc-aa79-c683122a1289}
死信队列收到消息 : {data=1631534588311, 正常队列消息,最大长度 5, messageId=7a7bd152-f2fa-4a74-b9e6-943ac7cbb3d4}
死信队列收到消息 : {data=1631534608504, 正常队列消息,最大长度 5, messageId=9de512a1-4ca4-4060-9096-27aba01c1687}
来源:https://blog.csdn.net/m0_46144826
(完)
码农突围资料链接1、卧槽!字节跳动《算法中文手册》火了,完整版 PDF 开放下载!
2、计算机基础知识总结与操作系统 PDF 下载
3、艾玛,终于来了!《LeetCode Java版题解》.PDF
4、Github 10K+,《LeetCode刷题C/C++版答案》出炉.PDF欢迎添加鱼哥个人微信:smartfish2020,进粉丝群或围观朋友圈
SpringBoot+RabbitMQ 死信队列相关推荐
- Rabbitmq死信队列
目录 1.什么是死信队列 2.产生死信队列的原因 3.代码实现---直连交换机 3.1.导入依赖 3.2.配置rabbitmq连接信息 3.3.编写配置类 3.4.编写生产者 3.5.编写消费者 3. ...
- Java秒杀系统实战系列~RabbitMQ死信队列处理超时未支付的订单(转)
转自: https://juejin.cn/post/6844903903130042376 文末有源代码,非常棒 摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十篇,本篇 ...
- RabbitMQ - 死信队列(DLX)
RabbitMQ - 死信队列(DLX) 配置死信队列 方式1 - RabbitMQ 管理后台配置死信队列 方式2 - 代码创建死信队列 验证 满足死信队列的条件 死信队列只是一个概念,本质就是普通的 ...
- 【分布式】Rabbitmq死信队列模型、实战场景---订单延迟30min支付处理
分布式 内容管理 死信队列 死信队列demo 死信队列消息模型 平台订单支付超时 --- 演示 业务分析 代码实现 RabbitMQ 死信队列/ 延迟队列 - 延迟业务逻辑 最近可能分布式进入Redi ...
- springboot集成rabbitmq死信队列的延时队列使用
目录 1.自动分列延时队列 2.应答失败自动转储延时再通知机制 ------------------------------------------------------------ ...
- SpringBoot RabbitMQ 延迟队列代码实现
场景 用户下单后,如果30min未支付,则删除该订单,这时候就要可以用延迟队列 准备 利用rabbitmq_delayed_message_exchange插件: 首先下载该插件:https://ww ...
- RabbitMQ死信队列应用
目录 1.什么是死信队列 2.死信队列应用场景 3.延迟消息概念 3.1 消息的TTL(Time To Live) 3.2 死信交换器 3.3 延时队列 4.死信队列使用流程图 5.死信队列应用(管理 ...
- RabbitMQ死信队列,延时队列
死信队列 消息被消费方否定确认,使用channel.basicNack或channel.basicReject, 并且此时requeue属性被设置为false. 消息在队列的存活时间超过设置的TTL时 ...
- 消息队列控制灯代码_代码实现RabbitMQ死信队列的创建
前言: 之前有写过死信队列的使用场景以及通过管控台创建死信.这次就通过代码实现死信队列的创建,同时也分享一下RabbitMQ封装的类. 准备: 1. 先准备一个死信队列(最后用来消费)的参 ...
最新文章
- Unity HDRP中的光照烘焙测试(Mixed Lighing )和间接光
- Codeforces Round #669 (Div. 2)
- python的print
- duilib清空richedit内容
- find linux 目录深度_浪里淘沙,详解Linux系统中Find命令的实用技巧
- fasttext 文本分类_4种常见的NLP实践思路【特征提取+分类模型】
- Java访问静态常量_Java如何在Spring EL中访问静态方法或常量?
- HTTP Headers Content-Disposition
- HDU 4079 Happy Telephones 简单题
- [转]vs2005(c#)水晶报表
- 详细了解 clientWidth、clientHeight、clientLeft、clientTop 以及几个常用的场景
- 讯飞语点,移动灵犀,搜狗语音助手对比测试
- 从今天开始,每天做一件有意义的事,有进步的事
- CSAPP:BombLab 详细解析
- ransomware(假的勒索病毒)逆向分析
- 电商网站数据库设计好文章分享
- MySQL 空间分析函数
- ARIMA模型来预测股票数据
- 针对尚硅谷教学微服务硅谷课堂在线学习平台的部分功能的自我改进
- BlueZ移植与配置(很全面)
热门文章
- DSP 2803x IIC/I2C总线
- mysql的mvvm_MVC、MVP、MVVM模式的概念与区别
- 认识Import表-PE输入表说明
- The Joel Test(祖尔测试)
- html防复制粘贴技术
- vue 图片宽高自适应
- flutter问题搜集
- 小字辈(c/c++)本题给定一个庞大家族的家谱,要请你给出最小一辈的名单。
- 2021年烟花爆竹产品涉药考试资料及烟花爆竹产品涉药考试平台
- c语言gcb最小公倍数,C编序编程题目:输入两个正整数m和n,求其最大公约数和最小公倍...,C语言编程,输入两个正整数M和N(MN),计算M和N...