当前位置: 首页 > article >正文

RabbitMQ高级特性--TTL和死信队列

目录

1.TTL

1.1设置消息的TTL

1.1.1配置交换机&队列

1.1.2发送消息

 1.1.3运行程序观察结果

1.2设置队列的TTL 

1.2.1配置队列和交换机的绑定关系

1.2.2发送消息

1.2.3运行程序观察结果

1.3两者区别

2.死信队列

2.1 声名队列和交换机

2.2正常队列绑定死信交换机

2.3制造死信产生的条件

2.4 发送消息

2.5测试死信 

 2.6常见面试题

2.6.1死信队列的概念

2.6.2死信的来源

2.6.3死信队列的应⽤场景


1.TTL

TTL(Time to Live, 过期时间), 即过期时间. RabbitMQ可以对消息和队列设置TTL.
当消息到达存活时间之后, 还没有被消费,就会被自动清除。

1.1设置消息的TTL

目前有两种方法可以设置消息的TTL

一是设置队列的TTL,队列中所有消息都有相同的过期时间,二是对消息本身进行单独设置,每条消息的TTL可以不同,如果两种方法一起使用,则消息的TTL以两者之间较小的那个数值决定。

先看针对每条消息设置TTL

针对每条消息设置TTL的方法是在发送消息的方法中加入expiration的属性参数,单位为ms

1.1.1配置交换机&队列

//TTL
public static final String TTL_QUEUE = "ttl_queue";
public static final String TTL_EXCHANGE_NAME = "ttl_exchange";//ttl
//1. 交换机
@Bean("ttlExchange")
public Exchange ttlExchange() {return
ExchangeBuilder.fanoutExchange(Constant.TTL_EXCHANGE_NAME).durable(true).build(
);
}
//2. 队列
@Bean("ttlQueue")
public Queue ttlQueue() {return QueueBuilder.durable(Constant.TTL_QUEUE).build();
}
//3. 队列和交换机绑定 Binding
@Bean("ttlBinding")
public Binding ttlBinding(@Qualifier("ttlExchange") FanoutExchange exchange, 
@Qualifier("ttlQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange);
}

1.1.2发送消息

@RequestMapping("/ttl")
public String ttl(){String ttlTime = "10000";//10srabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl 
test...", messagePostProcessor -> {messagePostProcessor.getMessageProperties().setExpiration(ttlTime);return messagePostProcessor;});return "发送成功!";
}

 1.1.3运行程序观察结果

发送消息后可以看到Ready数为1

十秒后,刷新页面发现消息已消失

1.2设置队列的TTL 

设置队列的TTL的方法是在创建队列时,加入x-message-ttl参数实现的,单位是ms

1.2.1配置队列和交换机的绑定关系

public static final String TTL_QUEUE2 = "ttl_queue2";
//设置ttl
@Bean("ttlQueue2")
public Queue ttlQueue2() {//设置20秒过期return QueueBuilder.durable(Constant.TTL_QUEUE2).ttl(20*1000).build();
}
//3. 队列和交换机绑定 Binding
@Bean("ttlBinding2")
public Binding ttlBinding2(@Qualifier("ttlExchange") FanoutExchange exchange, 
@Qualifier("ttlQueue2") Queue queue) {return BindingBuilder.bind(queue).to(exchange);
}

设置过期时间,也可以采用以下方式:

@Bean("ttlQueue2")
public Queue ttlQueue2() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-message-ttl",20000);//20秒过期return
QueueBuilder.durable(Constant.TTL_QUEUE2).withArguments(arguments).build();
}

1.2.2发送消息

@RequestMapping("/ttl")public String ttl() {
// String ttlTime = "30000";//10s
// //发送带ttl的消息
// rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl test...", //messagePostProcessor -> {
// messagePostProcessor.getMessageProperties().setExpiration(ttlTime);
// return messagePostProcessor;
// });//发送不带ttl的消息rabbitTemplate.convertAndSend(Constant.TTL_EXCHANGE_NAME, "", "ttl 
test...");return "发送成功!";}

1.2.3运行程序观察结果

 运行后发现,新增了一个队列,队列Features有一个TTL标识

 发送消息后,可以看到Ready消息为1

采⽤发布订阅模式, 所有与该交换机绑定的队列都会收到消息

20s后,刷新页面,发现消息已经删除

 

 由于ttl_queue队列, 未设置过期时间, 所以ttl_queue的消息未删除。

1.3两者区别

设置队列TTL属性的方法, ⼀旦消息过期, 就会从队列中删除
设置消息TTL的方法, 即使消息过期, 也不会马上从队列中删除, 而是在即将投递到消费者之前进⾏判定的
为什么这两种方法的处理方法不一致?
因为设置队列过期时间, 队列中已过期的消息肯定在队列头部, RabbitMQ只要定期从队头开始扫描是否有过期的消息即可.
而设置消息TTL的方式, 每条消息的过期时间不同, 如果要删除所有过期消息需要扫描整个队列, 所以不如等到此消息即将被消费时再判定是否过期, 如果过期再进行删除即可.

2.死信队列

死信(dead message)简单理解就是因为种种原因无法被消费的信息,就是死信

有死信,自然就有死信队列。当消息在一个队列中变成死信之后,它能被重新发送到另一个交换机中,这个交换机就是DLX(Dead Letter Exchange),绑定DLX的队列,就称为死信队列(Dead Letter Queue)简称DLQ

消息变成死信主要有以下几个原因:

1.消息被拒绝(Basic.Reject/Basic.Nack),并且设置requeue参数为false 

2.消息过期

3.队列达到最大长度

2.1 声名队列和交换机

//死信队列
public static final String DLX_EXCHANGE_NAME = "dlx_exchange";
public static final String DLX_QUEUE = "dlx_queue";
public static final String NORMAL_EXCHANGE_NAME = "normal_exchange";
public static final String NORMAL_QUEUE = “narmal_queue”;
/*** 死信队列相关配置*/
@Configuration
public class DLXConfig {//死信交换机@Bean("dlxExchange")public Exchange dlxExchange(){return
ExchangeBuilder.topicExchange(Constant.DLX_EXCHANGE_NAME).durable(true).build()
;}//2. 死信队列@Bean("dlxQueue")public Queue dlxQueue() {return QueueBuilder.durable(Constant.DLX_QUEUE).build();}//3. 死信队列和交换机绑定 Binding@Bean("dlxBinding")public Binding dlxBinding(@Qualifier("dlxExchange") Exchange exchange, 
@Qualifier("dlxQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("dlx").noargs();}//正常交换机@Bean("normalExchange")public Exchange normalExchange(){return
ExchangeBuilder.topicExchange(Constant.NORMAL_EXCHANGE_NAME).durable(true).buil
d();}//正常队列@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constant.NORMAL_QUEUE).build();}//正常队列和交换机绑定 Binding@Bean("normalBinding")public Binding normalBinding(@Qualifier("normalExchange") Exchange 
exchange, @Qualifier("normalQueue") Queue queue) {return BindingBuilder.bind(queue).to(exchange).with("normal").noargs();}
}

2.2正常队列绑定死信交换机

当这个队列中存在死信时,RabbitMQ会自动的把这个消息重新发布到设置的DLX上,进而被路由到另一个队列,即死信队列,可以监听这个死信队列中的消息以进行相应的处理

@Bean("normalQueue")
public Queue normalQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange",Constant.DLX_EXCHANGE_NAME);//绑定死信队列arguments.put("x-dead-letter-routing-key","dlx");//设置发送给死信队列的
RoutingKeyreturn QueueBuilder.durable(Constant.NORMAL_QUEUE).withArguments(arguments).build();
}

简写为

return QueueBuilder.durable(Constant.NORMAL_QUEUE).deadLetterExchange(Constant.DLX_EXCHANGE_NAME).deadLetterRoutingKey("dlx").build();

2.3制造死信产生的条件

@Bean("normalQueue")
public Queue normalQueue() {Map<String, Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange",Constant.DLX_EXCHANGE_NAME);//绑定死
信队列arguments.put("x-dead-letter-routing-key","dlx");//设置发送给死信队列的
RoutingKey//制造死信产⽣的条件arguments.put("x-message-ttl",10000);//10秒过期arguments.put("x-max-length",10);//队列⻓度return
QueueBuilder.durable(Constant.NORMAL_QUEUE).withArguments(arguments).build();
}

简写为:

return QueueBuilder.durable(Constant.NORMAL_QUEUE).deadLetterExchange(Constant.DLX_EXCHANGE_NAME).deadLetterRoutingKey("dlx").ttl(10*1000).maxLength(10L).build();

2.4 发送消息

@RequestMapping("/dlx")public void dlx() {//测试过期时间, 当时间达到TTL, 消息⾃动进⼊到死信队列rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal", 
"dlx test...");//测试队列⻓度
// for (int i = 0; i < 20; i++) {
// rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal", "dlx test...");
// }
// //测试消息拒收
// rabbitTemplate.convertAndSend(Constant.NORMAL_EXCHANGE_NAME, "normal", "dlx test...");}

2.5测试死信 

 程序启动后观察队列:

队列Features说明:
D: durable的缩写, 设置持久化
TTL: Time to Live, 队列设置了TTL
Lim: 队列设置了⻓度(x-max-length)
DLX: 队列设置了死信交换机(x-dead-letter-exchange)
DLK: 队列设置了死信RoutingKey(x-dead-letter-routing-key)
测试过期时间,到达过期时间后,进入死信队列:
发送之后:

 10s后:

⽣产者⾸先发送⼀条消息,然后经过交换器(normal_exchange)顺利地存储到队列(normal_queue)中.由于队列normal_queue设置了过期时间为10s, 在这10s内没有消费者消费这条消息, 那么判定这条消息过期. 由于设置了DLX, 过期之时, 消息会被丢给交换器(dlx_exchange)中, 这时根据RoutingKey匹配, 找到匹配的队列(dlx_queue), 最后消息被存储在queue.dlx这个死信队列里。

 2.6常见面试题

死信队列作为RabbitMQ的高级特性,也是面试的一大重点

2.6.1死信队列的概念

死信(Dead Letter)是消息队列中的⼀种特殊消息, 它指的是那些⽆法被正常消费或处理的消息. 在消息队列系统中, 如RabbitMQ, 死信队列用于存储这些死信消息

2.6.2死信的来源

1) 消息过期: 消息在队列中存活的时间超过了设定的TTL
2) 消息被拒绝: 消费者在处理消息时, 可能因为消息内容错误, 处理逻辑异常等原因拒绝处理该消息. 如果拒绝时指定不重新⼊队(requeue=false), 消息也会成为死信.
3) 队列满了: 当队列达到最大长度, 无法再容纳新的消息时, 新来的消息会被处理为死信.

2.6.3死信队列的应⽤场景

对于RabbitMQ来说, 死信队列是⼀个⾮常有⽤的特性. 它可以处理异常情况下,消息不能够被消费者正确消费而被置⼊死信队列中的情况, 应⽤程序可以通过消费这个死信队列中的内容来分析当时所遇到的
异常情况, 进而可以改善和优化系统.
⽐如: 用户支付订单之后, ⽀付系统会给订单系统返回当前订单的⽀付状态
为了保证⽀付信息不丢失, 需要使⽤到死信队列机制. 当消息消费异常时, 将消息投⼊到死信队列中, 由订单系统的其他消费者来监听这个队列, 并对数据进行处理(比如发送⼯单等,进行人工确认).
场景的应⽤场景还有:
消息重试:将死信消息重新发送到原队列或另⼀个队列进行重试处理.
消息丢弃:直接丢弃这些⽆法处理的消息,以避免它们占⽤系统资源.
⽇志收集:将死信消息作为⽇志收集起来,⽤于后续分析和问题定位

相关文章:

RabbitMQ高级特性--TTL和死信队列

目录 1.TTL 1.1设置消息的TTL 1.1.1配置交换机&队列 1.1.2发送消息 1.1.3运行程序观察结果 1.2设置队列的TTL 1.2.1配置队列和交换机的绑定关系 1.2.2发送消息 1.2.3运行程序观察结果 1.3两者区别 2.死信队列 2.1 声名队列和交换机 2.2正常队列绑定死信交换机 …...

Java后端开发: 如何安装搭建Java开发环境《安装JDK》和 检测JDK版本

文章目录 一、JDK的安装1、 打开 Oracle 官方网址2、点击产品 二、检测JDK是否安装成功以及JDK版本的查看1. 打开命令行窗口检测是否安装成功查看 JDK 版本 一、JDK的安装 1、 打开 Oracle 官方网址 Oracle官网地址:https://www.oracle.com/cn/ 2、点击产品 打开下载的JDK文件…...

LabVIEW液压控制系统开发要点

液压控制系统开发需兼顾高实时性、强抗干扰性和安全性&#xff0c;尤其在重工业场景中&#xff0c;毫秒级响应延迟或数据异常都可能导致设备损坏。本文以某钢厂液压升降平台项目为例&#xff0c;从硬件选型、控制算法、安全机制三方面&#xff0c;详解LabVIEW开发中的关键问题与…...

鸿蒙Flutter实战:18-组合而非替换,现有插件快速鸿蒙化

引言 在对插件鸿蒙化时&#xff0c;除了往期文章现有Flutter项目支持鸿蒙II中讲到的使用 dependency_overrides 来配置鸿蒙适配库的两种方式以外&#xff0c;如果三方插件本身使用了联合插件的形式&#xff0c;也可以通过下面这种方式来添加鸿蒙平台的实现&#xff1a; depen…...

Qt之Service开发

一、概述 基于Qt的用于开发系统服务(守护进程)和后台服务,有以下几个优秀的开源 QtService 框架和库。 1. QtService (官方解决方案) GitHub: https://github.com/qtproject/qt-solutions/tree/master/qtservice 特点: 官方提供的服务框架 支持 Windows 服务和 Linux 守护…...

MFC添加免费版大漠3.1233

先创建一个MFC工程&#xff0c; 添加dm.dll 方法一&#xff1a;通过类向导-添加类-类型库中的MFC类-文件&#xff0c;选择dm.dll&#xff0c;如果没有"添加类型库中的MFC类"选项就用方法二添加 方法二&#xff1a;添加-新建项-MFC-Active或TypeLib-实现接口位置选…...

vue 图片放大到全局

背景&#xff1a; 在vue项目中&#xff0c;el-image组件图片组件用于展示图片&#xff0c;组件自带的属性preview-teleported&#xff0c;设置为true可以控制图片放大到全局 实现效果&#xff1a; 核心代码&#xff1a; //图片地址&#xff1a;BASEUrl /file/ item.file //这…...

人工智能入门(1)

人工智能导引 文章目录 人工智能导引artifiicial intelligence由图灵测试出发的六个领域贝叶斯方法分析成为大多数AI系统中不确定推理的现代方法基础 研究方法 机器学习计算机利用已经有的数据样本&#xff0c;得出某种规律模型&#xff0c;并利用模型预测未来的一种方法 回归算…...

Python爬虫:Feapder 的详细使用和案例

更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 1. Feapder 概述1.1 Feapder介绍1.2 Feapder 核心特点1.3 Feapder 主要组件1.4 Feapder的安装2. 基础爬虫编写2.1 创建爬虫2.2 运行爬虫3. 数据采集案例3.1 新闻网站采集3.2 电商商品采集3.3 使用 Spider 类创建更强大爬…...

mybatis里in关键字拼接id问题

我们一般会把ids集合用StrUtil.join(‘,’)转成"1,2,3"这种形式 然后放入in中 我们会这么写: select id, nick_name, icon from tb_user where id in (#{ids}) order by FIELD(id, #{ids})结果发现sql执行是这样的: select id, nick_name, icon from tb_user where…...

在rockylinux9.4安装mongodb报错:缺少:libcrypto.so.10文件库

问题点&#xff1a; rockylinux9.4系统环境报错&#xff1a; ./mongod: error while loading shared libraries: libcrypto.so.10: cannot open shared object file: No such file or directory 解决方法&#xff1a; Ps&#xff1a;解压之后&#xff0c;检查mongodb的依赖环境…...

Spring Boot集成阿里云OSS:对象存储实战指南

Spring Boot集成阿里云OSS&#xff1a;对象存储实战指南 1. OSS是什么&#xff1f;为什么选择阿里云OSS&#xff1f; 对象存储&#xff08;OSS&#xff09; 是一种用于存储非结构化数据&#xff08;如图片、视频、日志文件&#xff09;的云服务&#xff0c;核心功能包括&#…...

【力扣hot100题】(019)旋转图像

比较考验脑子转不转得过来&#xff0c;最好先在纸上画一下图整理思路&#xff0c;不要和我一样上来就无脑套循环。 理解了思路还是好做的&#xff0c;每个小循环转一圈&#xff0c;大循环代表转的第几圈。小循环循环n-2i-1次&#xff0c;大循环循环&#xff08;n1&#xff09;…...

06_约束

文章目录 一、是什么二、实体完整性约束2.1、主键约束2.2、主键自增长2.3、唯一约束 三、域完整性约束3.1、非空约束3.2、默认值 四、引用完整性约束 一、是什么 用于限制加入表的数据的类型和规范&#xff0c;约束是添加在列上的&#xff0c;用来约束列的。 分类&#xff1a; …...

Anolis OS 8.4修复CVE-1999-0554漏洞记录

1. 使用TCP Wrappers配置白名单 通过修改/etc/hosts.allow和/etc/hosts.deny文件&#xff0c;仅允许特定IP访问NFS的mountd服务&#xff08;需确保系统支持TCP Wrappers&#xff09;&#xff1a; 编辑/etc/hosts.allow&#xff0c;添加允许的客户端IP&#xff08;如192.168.1…...

Seata AT模式的一些常见问题及其源码解析

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和 XA 事务模式&#xff0c;为用户打造一站式的分布式解决方案。 Seata AT 基于两阶段提交协议的演变&#xff1a; 一阶段&#xff1a;业…...

华为GaussDB数据库的手动备份与还原操作介绍

数据库的备份以A机上的操作为例。 1、使用linux的root用户登录到GaussDB服务器。 2、用以下命令切换到 GaussDB 管理员用户&#xff0c;其中&#xff0c;omm 为当前数据库的linux账号。 su - omm 3、执行gs_dump命令进行数据库备份&#xff1a; 这里使用gs_dump命令进行备…...

2025年3月29日(matlab -ss -lti)

线性时不变系统&#xff08;LTI系统&#xff09;的定义与核心特性 线性时不变系统&#xff08;Linear Time-Invariant System&#xff09;是信号与系统分析中的基础模型&#xff0c;其核心特性包括线性和时不变性。以下从定义、验证方法和应用场景展开说明&#xff1a; 1. 线性…...

网络原理-TCP/IP

网络原理学习笔记&#xff1a;TCP/IP 核心概念 本文是我在学习网络原理时整理的笔记&#xff0c;主要涵盖传输层、网络层和数据链路层的核心协议和概念&#xff0c;特别是 TCP, UDP, IP, 和以太网。 一、传输层 (Transport Layer) 传输层负责提供端到端&#xff08;进程到进…...

服务器磁盘卷组缓存cache设置介绍

工具1&#xff1a; storcli a. 确认软件包是否安装 [rootlocalhost ~]#rpm -qa | grep storcli storcli-1.21.06-1.noarch 备注&#xff1a;若检索结果为空&#xff0c;需要安装对应的软件安装包。安装命令如下&#xff1a; #rpm -ivh storcli-xx-xx-1.noarch.rpm b. 查看逻辑…...

Unity顶点优化:UV Splits与Smoothing Splits消除技巧

一、顶点分裂问题概述 1. 什么是顶点分裂 顶点分裂(Vertex Splits)是3D渲染中常见的性能问题&#xff0c;当模型需要为同一顶点位置存储不同属性值时&#xff0c;会创建多个顶点副本。主要分为两类&#xff1a; UV Splits&#xff1a;由UV不连续引起 Smoothing Splits&#…...

第五十三章 Spring之假如让你来写Boot——环境篇

Spring源码阅读目录 第一部分——IOC篇 第一章 Spring之最熟悉的陌生人——IOC 第二章 Spring之假如让你来写IOC容器——加载资源篇 第三章 Spring之假如让你来写IOC容器——解析配置文件篇 第四章 Spring之假如让你来写IOC容器——XML配置文件篇 第五章 Spring之假如让你来写…...

Router [Continuation Settings]

楼上网络CMCC-Wmew&#xff0c;楼下接收不到&#xff0c;可能因为喜好弱&#xff0c;再弄一台路由器中转一下 Router [Continuation Settings] 路由器中续设置 到这里这台K3的路由器设置完成了&#xff0c;作为转发&#xff0c;中续&#xff0c;她还需要设置上游路由器&#…...

Zookeeper中的Zxid是如何设计的

想获取更多高质量的Java技术文章&#xff1f;欢迎访问Java技术小馆官网&#xff0c;持续更新优质内容&#xff0c;助力技术成长 Java技术小馆官网https://www.yuque.com/jtostring Zookeeper中的Zxid是如何设计的 如果你们之前学习过 ZooKeeper&#xff0c;你们可能已经了解…...

蓝桥云客 岛屿个数

0岛屿个数 - 蓝桥云课 问题描述 小蓝得到了一副大小为 MN 的格子地图&#xff0c;可以将其视作一个只包含字符 0&#xff08;代表海水&#xff09;和 1&#xff08;代表陆地&#xff09;的二维数组&#xff0c;地图之外可以视作全部是海水&#xff0c;每个岛屿由在上/下/左/右…...

深度学习篇---paddleocr正则化提取

文章目录 前言一、代码总述&介绍1.1导入必要的库1.1.1cv21.1.2re1.1.3paddleocr 1.2初始化PaddleOCR1.3打开摄像头1.4使用 PaddleOCR 进行识别1.5定义正则表达式模式1.6打印提取结果1.7异常处理 二、正则表达式2.1简介2.2常用正则表达式模式及原理2.2.1. 快递单号模式2.2.2…...

Android 蓝牙/Wi-Fi通信协议之:低功耗蓝牙(BLE 4.0+)介绍

介绍&#xff1a;蓝牙通信协议详解 1. 蓝牙协议分层 Android主要支持**经典蓝牙&#xff08;Bluetooth Classic&#xff09;和低功耗蓝牙&#xff08;BLE&#xff09;**两种模式&#xff1a; 经典蓝牙&#xff08;BT 2.1/3.0&#xff09; 低功耗蓝牙&#xff08;BLE 4.0&…...

流影---开源网络流量分析平台(四)(分析引擎部署)

目录 功能介绍 部署过程 一、安装依赖环境 二、源码编译部署 三、运行环境配置 四、运行配置 功能介绍 本章我将继续安装流影的分析引擎组件首先&#xff0c;ly_analyser是流影的威胁行为分析引擎&#xff0c;读取netflow v9格式的数据作为输入&#xff0c;运行各种威胁行…...

31天Python入门——第14天:异常处理

你好&#xff0c;我是安然无虞。 文章目录 异常处理1. Python异常2. 异常捕获try-except语句捕获所有的异常信息获取异常对象finally块 3. raise语句4. 自定义异常5. 函数调用里面产生的异常补充练习 异常处理 1. Python异常 Python异常指的是在程序执行过程中发生的错误或异…...

浅析Android Jetpack ACC之LiveData

一、Android Jetpack简介 Android官网对Jetpack的介绍如下&#xff1a; Jetpack is a suite of libraries to help developers follow best practices, reduce boilerplate code, and write code that works consistently across Android versions and devices so that develo…...