rabbitMQ死信队列快速编写记录
文章目录
- 1.介绍
- 1.1 什么是死信队列
- 1.2 死信队列有什么用
- 2. 如何编码
- 2.1 架构分析
- 2.2 maven坐标
- 2.3 工具类编写
- 2.4 consumer1编写
- 2.5 consumer2编写
- 2.6 producer编写
- 3.整合springboot
- 3.1 架构图
- 3.2 maven坐标
- 3.3 构建配置类,创建exchange,queue,并绑定
- 3.4 编写生产者(controller的一个方法)
- 3.5 编写消费者(一个类, 方法上加上@RabbitListenner,表明需要监听的queue)
- 4. 常见参数汇总
1.介绍
1.1 什么是死信队列
再rabbitMQ中,有两个重要的组件。exchange(交换机),queue(队列)。交换机用于路由消息,简单来说就是接收客户端传递的消息,转发到queue中。队列做的事情就是存储消息。
但消息并不会一只存储在队列中。当存在一下三种情况,消息就会死掉
- 队列存储不了过多的消息
- 消息本身存在过期时间
当遇到死掉的消息时,我们通常会将这些死信转发到新的交换机中,这个交换机就叫做死信交换机,而配合死信交换机存储信息的队列,叫做死信队列
1.2 死信队列有什么用
死信队列在构建延迟队列时,有巨大作用。比如用户购票订单,30min不支付就过期。在rabbitMQ中可以这样实现
- 1 存储购票信息到
exchange-queue中 - 2 设置消息过期时间为30min
- 3 如果超过30min消息未被消费(消息过期,成为死信),存储死信队列,通知服务取消订单
2. 如何编码
2.1 架构分析
先上绑定架构图

整个流程中,出现了三方。在编写代码时,我们可以分三个大类,分别是producer,consumer1,consumer2。其消息传递顺序如下
producer-> normal_exchange- normal_queue ->
consumer1 - dead_queue->
consumer2
我们可以在编写consumer1的时候,完成exchange和queue的创建与绑定
2.2 maven坐标
<dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.9.0</version></dependency>
2.3 工具类编写
rabbitMQ整体的编写流程如下
- 创建Connection工厂
- 配置工厂
- 创建链接
- 获取channel
- 通过channel创建exchange, queue, 关系绑定, 监听消息, 发送消息
因此,我们可以先创建工具类,帮我们获取channel,以此减少开发代码量
public class MQUtils {public static Channel getChannel() throws Exception {// 创建工厂链接ConnectionFactory factory = new ConnectionFactory();// 设置工厂factory.setHost("your_ip");factory.setUsername("your_username");factory.setPassword("your_password");factory.setVirtualHost("/"); // 基本都是/Connection connection = factory.newConnection();Channel channel = connection.createChannel();return channel;}
}
2.4 consumer1编写
public class Consumer1 {static String EXCHANGE_NAME = "normal_exchange";static String QUEUE_NAME = "normal_queue";static String DEAD_EXCHANGE_NAME = "dead_exchange";static String DEAD_QUEUE_NAME = "dead_queue";public static void main(String[] args) throws Exception{Channel channel = MQUtils.getChannel();// 普通交换机channel.exchangeDeclare(EXCHANGE_NAME, BuiltinExchangeType.DIRECT, false, true, null);// 普通队列// 配置死信交换机参数HashMap<String, Object> map = new HashMap<>();// 配置normal_queue连接的dead_exchangemap.put("x-dead-letter-exchange", DEAD_EXCHANGE_NAME);// 设置normal_queue的消息过期时间map.put("x-message-ttl", 10000);// 设置路由到死信交换机的路由key: lisimap.put("x-dead-letter-routing-key", "lisi");// map.put("x-max-length", 6); // 设置队列最大长度channel.queueDeclare(QUEUE_NAME, false, false, true, map);// 绑定普通交换机和普通队列channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "zhangsan");// 死信交换机channel.exchangeDeclare(DEAD_EXCHANGE_NAME, BuiltinExchangeType.DIRECT, false, true, false, null);// 死信队列channel.queueDeclare(DEAD_QUEUE_NAME, false, false, true, null);// 绑定死信交换机和死信队列channel.queueBind(DEAD_QUEUE_NAME, DEAD_EXCHANGE_NAME, "lisi");// 监听channel.basicConsume(QUEUE_NAME, false, (consumerTag, message) -> {System.out.println("监听普通队列: " + new String(message.getBody()));}, consumerTag -> {});}
}
2.5 consumer2编写
public class Consumer2{static String DEAD_QUEUE_NAME = "dead_queue";public static void main(String[] args) throws Exception{Channel channel = MQUtils.getChannel();// 监听channel.basicConsume(DEAD_QUEUE_NAME, true, (consumerTag, message) -> {System.out.println("监听死信队列: " + new String(message.getBody()));}, consumerTag -> {});}
}
2.6 producer编写
public class Producer {static String EXCHANGE_NAME = "normal_exchange";public static void main(String[] args) throws Exception{Channel channel = MQUtils.getChannel();for (int i = 0; i < 10; i++) {String msg = i + "";channel.basicPublish(EXCHANGE_NAME, "zhangsan",null,msg.getBytes());}}
}
3.整合springboot
3.1 架构图

3.2 maven坐标
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId><version>2.3.9.RELEASE</version></dependency>
3.3 构建配置类,创建exchange,queue,并绑定
package com.xhf.mq.config;import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class TTLConfig {/*-----交换机名称-----*/private static final String EXCHANGE_NAME = "X";private static final String DEAD_EXCHANGE_NAME = "Y";/*-----队列名称-----*/private static final String QUEUE_NAME1 = "QA";private static final String QUEUE_NAME2 = "QB";private static final String DEAD_QUEUE_NAME = "QD";// 注册交换机@Bean("xExchange")public DirectExchange xExchange() {return ExchangeBuilder.directExchange(EXCHANGE_NAME).autoDelete().build();
// return new DirectExchange(EXCHANGE_NAME);}// 注册死信交换机@Bean("deadExchange")public DirectExchange deadExchange() {return ExchangeBuilder.directExchange(DEAD_EXCHANGE_NAME).autoDelete().build();}// 注册队列QA@Bean("queueA")public Queue queueA() {return QueueBuilder.nonDurable(QUEUE_NAME1).withArgument("x-message-ttl", 10000).withArgument("x-dead-letter-exchange", DEAD_EXCHANGE_NAME).withArgument("x-dead-letter-routing-key", "YD").build();}// 注册队列QB@Bean("queueB")public Queue queueB() {return QueueBuilder.nonDurable(QUEUE_NAME2).withArgument("x-message-ttl", 40000).withArgument("x-dead-letter-exchange", DEAD_EXCHANGE_NAME).withArgument("x-dead-letter-routing-key", "YD").build();}// 注册队列QD@Bean("queueD")public Queue queueD() {return QueueBuilder.nonDurable(DEAD_QUEUE_NAME).build();}// 绑定普通交换机, 队列@Beanpublic Binding queueABindingX(@Qualifier("queueA") Queue queueA, @Qualifier("xExchange") Exchange xExchange) {return BindingBuilder.bind(queueA).to(xExchange).with("XA").and(null);}@Beanpublic Binding queueBBindingX(@Qualifier("queueB") Queue queueB, @Qualifier("xExchange") Exchange xExchange) {return BindingBuilder.bind(queueB).to(xExchange).with("XB").and(null);}// 绑定死信交换机, 队列@Beanpublic Binding queueDBindingY(@Qualifier("queueD") Queue queueD, @Qualifier("deadExchange") Exchange deadExchange) {return BindingBuilder.bind(queueD).to(deadExchange).with("YD").and(null);}
}
3.4 编写生产者(controller的一个方法)
@GetMapping("/sendToQA")public void sendToQA() {// 向X交换机发送消息, 消息通过"XA"路由到队列rabbitTemplate.convertAndSend("X", "XA", "hello".getBytes());}
3.5 编写消费者(一个类, 方法上加上@RabbitListenner,表明需要监听的queue)
@Component
public class Customer {@RabbitListener(queues = "QD")public void customer(Message message, Channel channel) {byte[] body = message.getBody();System.out.println(new String(body));}
}
4. 常见参数汇总
- x-dead-letter-exchange :死信交换机名称
- x-message-ttl:消息time to live时间(过期时间)
- x-dead-letter-routing-key:死信交换机路由key
- x-max-length:队列最大长度
相关文章:
rabbitMQ死信队列快速编写记录
文章目录 1.介绍1.1 什么是死信队列1.2 死信队列有什么用 2. 如何编码2.1 架构分析2.2 maven坐标2.3 工具类编写2.4 consumer1编写2.5 consumer2编写2.6 producer编写 3.整合springboot3.1 架构图3.2 maven坐标3.3 构建配置类,创建exchange,queue&#x…...
数位dp,338. 计数问题
338. 计数问题 - AcWing题库 给定两个整数 a 和 b,求 a 和 b 之间的所有数字中 0∼90∼9 的出现次数。 例如,a1024,b1032,则 a 和 b 之间共有 9 个数如下: 1024 1025 1026 1027 1028 1029 1030 1031 1032 其中 0 出…...
如何解决git clone http/https仓库失败(403错误)
本来不打算写这篇文章,但是后来又遇到这个问题忘了之前是怎么解决的了。 一般情况下,个人使用 GitHub 等平台时是使用 SSH 协议的,这样不光方便管理可访问用户,也保证了安全性。但是 GitHub 上仓库的 SSH 地址是要登陆才能看到&a…...
华为云云耀云服务器L实例评测 | 实例评测使用之硬件性能评测:华为云云耀云服务器下的硬件运行评测
华为云云耀云服务器L实例评测 | 实例评测使用之硬件性能评测:华为云云耀云服务器下的硬件运行评测 介绍华为云云耀云服务器 华为云云耀云服务器 (目前已经全新升级为 华为云云耀云服务器L实例) 华为云云耀云服务器是什么华为云云耀…...
Elasticsearch:使用 Elasticsearch 进行语义搜索
在数字时代,搜索引擎在通过浏览互联网上的大量可用信息来检索数据方面发挥着重要作用。 此方法涉及用户在搜索栏中输入特定术语或短语,期望搜索引擎返回与这些确切关键字匹配的结果。 虽然关键字搜索对于简化信息检索非常有价值,但它也有其局…...
JVM的主要组成及其作用
jvm主要组成部分有: 类加载器、运行时数据区 (内存结构)、执行引擎、本地接口库、垃圾回收机制 Java程序运行的时候,首先会通过类加载器把Java 代码转换成字节码。然后运行时数据区再将字节码加载到内存中,但字节码文件只是JVM 的一套指令集规范…...
会议AISTATS(Artificial Intelligence and Statistics) Latex模板参考文献引用问题
前言 在看AISTATS2024模板的时候,发现模板里面根本没有教怎么引用,要被气死了。 如下,引用(Cheesman, 1985)的时候,模板是自己手打上去的?而且模板提供的那三个引用,根本也没有Cheesman这个人,…...
2023最新外贸建站:WordPress搭建外贸独立站零基础小白保姆级教程
想从零开始建立一个外贸自建站,那么你来对地方了。 如果你还在找外贸建站或者是WordPress建站教程,不妨看看这篇文章,本教程涵盖了2023最新的外贸建站教程,你将学会使用WordPress自建外贸独立站,步骤包括购买域名主机…...
HTTP请求交互基础(基于GPT3.5,持续更新)
HTTP交互基础 目的HTTP定义详解HTTP协议(规范)1. 主要组成部分1.1 请求行(Request Line):包含请求方法、请求URI(Uniform Resource Identifier)和HTTP协议版本。1.2 请求头部(Reques…...
小谈设计模式(6)—依赖倒转原则
小谈设计模式(6)—依赖倒转原则 专栏介绍专栏地址专栏介绍 依赖倒转原则核心思想关键点分析abc 优缺点分析优点降低模块间的耦合度提高代码的可扩展性便于进行单元测试 缺点增加代码的复杂性需要额外的设计和开发工作 Java代码实现示例分析 总结 专栏介绍…...
JetBrains常用插件
Codota AI Autocomplete Java and JavaScript:自动补全插件 Background Image plus:背景图片设置 rainbow brackets:彩虹括号,便于识别 CodeGlance2: 类似于 Sublime 中的代码缩略图(代码小地图ÿ…...
【C++哈希应用】位图、布隆过滤器
【C哈希应用】位图、布隆过滤器 目录 【C哈希应用】位图、布隆过滤器位图概念位图的实现位图改造位图应用总结布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的查找布隆过滤器删除布隆过滤器优点布隆过滤器缺陷 作者:爱写代码的刚子 时间:2023.9…...
Qt 编译纯c的C99的项目, error: undefined reference to `f()‘
把Cpp的后缀该为C是什么样的 尝试引用一个奇门排盘的c程序,在git上找到的叫cqm, 然后总是报错 error: undefined reference to f() 很是郁闷 于是新建了个项目试验一下,终于摸清了需要命名空间。 后来这么写就可以了 a.h namespace XX …...
TensorFlow入门(五、指定GPU运算)
一般情况下,下载的TensorFlow版本如果是GPU版本,在运行过程中TensorFlow能自动检测。如果检测到GPU,TensorFlow会默认利用找到的第一个GPU来执行操作。如果机器上有超过一个可用的GPU,除第一个之外的其他GPU默认是不参与计算的。如果想让TensorFlow使用这些GPU执行操作,需要将运…...
Unity - 实践: Metallic流程贴图 转 Specular流程贴图
文章目录 目的Metallic Flow - SP - 输出输出的 MRA (MGA) 贴图 Metallic->Specular (根据教程一步一步实践)1. Base color Metallic -> Diffuse2. Base color Metallic -> Specular3. Roughness -> Glossiness输出贴图,在 unity 中展示:M…...
第三章:最新版零基础学习 PYTHON 教程(第四节 - Python 运算符—Python 逻辑运算符及示例)
运算符用于对值和变量执行操作。这些是执行算术和逻辑计算的特殊符号。运算符运算的值称为操作数。 表中的内容逻辑运算符 逻辑与运算符 逻辑或运算符 逻辑非运算符 逻辑运算符的求值顺序 逻辑运算符 在 Python 中,逻辑运算符用于条件语句(True 或 False)。它们执行逻辑 AN…...
如何做好测试?(三)功能测试 (Functional Testing, FT)
1. 功能测试的详细介绍: 功能测试 (Functional Testing, FT),是一种软件测试方法,旨在验证系统的功能是否按照需求规格说明书或用户期望的方式正常工作。它关注系统的整体行为,以确保各个功能模块和组件之间的交互和集成正确。 …...
Ubuntu-Server-22.04安装桌面+VNC
前提:Ubuntu Server安装好后,ubantu其他版本是否适用这里未知,欢迎大佬们前来评论 一、默认没有图形界面,有时觉得用图形界面操作更简单直接,于是用如下命令安装: 1.更新本地环境 sudo apt-get update s…...
职业规划,什么是职业兴趣 - 我喜欢做什么?
能够在工作岗位上面做出成绩的人,都是结合自身兴趣,对职业进行合理规划的那一类。尤其是步入中年以后,能够创造出巨大价值的人,无一例外都是喜欢自己职业的人。没有将兴趣融入工作的人,只能够忍受默默无闻地活着&#…...
基于Java的高校学生党员发展流程管理系统设计与实现(源码+lw+部署文档+讲解等)
文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…...
PHP和Node.js哪个更爽?
先说结论,rust完胜。 php:laravel,swoole,webman,最开始在苏宁的时候写了几年php,当时觉得php真的是世界上最好的语言,因为当初活在舒适圈里,不愿意跳出来,就好比当初活在…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词
Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵,其中每行,每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid,其中有多少个 3 3 的 “幻方” 子矩阵&am…...
听写流程自动化实践,轻量级教育辅助
随着智能教育工具的发展,越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式,也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建,…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
高抗扰度汽车光耦合器的特性
晶台光电推出的125℃光耦合器系列产品(包括KL357NU、KL3H7U和KL817U),专为高温环境下的汽车应用设计,具备以下核心优势和技术特点: 一、技术特性分析 高温稳定性 采用先进的LED技术和优化的IC设计,确保在…...
Redis上篇--知识点总结
Redis上篇–解析 本文大部分知识整理自网上,在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库,Redis 的键值对中的 key 就是字符串对象,而 val…...
表单设计器拖拽对象时添加属性
背景:因为项目需要。自写设计器。遇到的坑在此记录 使用的拖拽组件时vuedraggable。下面放上局部示例截图。 坑1。draggable标签在拖拽时可以获取到被拖拽的对象属性定义 要使用 :clone, 而不是clone。我想应该是因为draggable标签比较特。另外在使用**:clone时要将…...
背包问题双雄:01 背包与完全背包详解(Java 实现)
一、背包问题概述 背包问题是动态规划领域的经典问题,其核心在于如何在有限容量的背包中选择物品,使得总价值最大化。根据物品选择规则的不同,主要分为两类: 01 背包:每件物品最多选 1 次(选或不选&#…...
