消息队列-RabbitMQ:死信队列

十五、死信队列

1、死信的概念

先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,一般来说,producer 将消息投递到 broker 或者直接到 queue 里了,consumer 从 queue 取出消息进行消费,但某些时候由于特定的原因导致 queue 中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列

应用场景:为了保证订单业务的消息数据不丢失,需要使用到 RabbitMQ 的死信队列机制,当消息消费发生异常时,将消息投入死信队列中。还有比如说:用户在商城下单成功并点击去支付后在指定时间未支付时自动失效

2、死信的来源

  • 消息 TTL 过期:TTL 是 Time To Live 的缩写,也就是生存时间。

  • 队列达到最大长度:队列满了,无法再添加数据到 mq 中。

  • 消息被拒绝:(basic.reject 或 basic.nack) 并且 requeue=false。

3、死信实战

在这里插入图片描述

死信之 TTL

(1)消费者1

①定义普通交换机、死信交换机与正常队列、死信队列

②声明死信交换机、普通交换机与普通队列

③设置正常队列和死信交换机的联系,使用argument参数

④绑定:普通交换机和正常队列、死信交换机和死信队列

⑤正常接收消息

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

public class Consumer01 {//普通交换机名称private static final String NORMAL_EXCHANGE = "normal_exchange";//死信交换机名称private static final String DEAD_EXCHANGE = "dead_exchange";public static void main(String[] args) throws Exception {Channel channel = RabbitMqUtils.getChannel();//声明死信和普通交换机 类型为 directchannel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);//声明死信队列String deadQueue = "dead-queue";channel.queueDeclare(deadQueue, false, false, false, null);//死信队列绑定:队列、交换机、路由键(routingKey)channel.queueBind(deadQueue, DEAD_EXCHANGE, "lisi");//正常队列绑定死信队列信息Map<String, Object> params = new HashMap<>();//正常队列设置死信交换机 参数 key 是固定值params.put("x-dead-letter-exchange", DEAD_EXCHANGE);//正常队列设置死信 routing-key 参数 key 是固定值params.put("x-dead-letter-routing-key", "lisi");//正常队列String normalQueue = "normal-queue";channel.queueDeclare(normalQueue, false, false, false, params);channel.queueBind(normalQueue, NORMAL_EXCHANGE, "zhangsan");System.out.println("等待接收消息........... ");DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println("Consumer01 接收到消息" + message);};channel.basicConsume(normalQueue, true, deliverCallback, consumerTag -> {});}}

(2)生产者:

①定义普通交换机的名称

②设置消息的TTL,死信消息的设置

③正常发送消息

在这里插入图片描述

public class Producer {private static final String NORMAL_EXCHANGE = "normal_exchange";public static void main(String[] argv) throws Exception {Channel channel = RabbitMqUtils.getChannel();channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);//设置消息的 TTL 时间 10sAMQP.BasicProperties properties = new AMQP.BasicProperties().builder().expiration("10000").build();//该信息是用作演示队列个数限制for (int i = 1; i < 11; i++) {String message = "info" + i;channel.basicPublish(NORMAL_EXCHANGE, "zhangsan", properties, message.getBytes());System.out.println("生产者发送消息:" + message);}}
}

(3)测试效果1:

先启动消费者1,再启动生产者

在这里插入图片描述

注意:正常交换机的Features里面多了 DLX、DLK

在这里插入图片描述

在这里插入图片描述

(4)正常队列和死信队列中消息数的变化对比

在这里插入图片描述

当正常队列的消息TTL到了之后,还没有被接受,正常队列的消息会被转发到死信交换机,再到死信队列里面,这个过程很快的

在这里插入图片描述

(5)消费者2

接收死信队列的消息即可

在这里插入图片描述

public class Consumer02 {//死信交换机名称private static final String DEAD_EXCHANGE = "dead_exchange";public static void main(String[] args) throws Exception {Channel channel = RabbitMqUtils.getChannel();//声明交换机channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);//声明队列String deadQueue = "dead-queue";channel.queueDeclare(deadQueue, false, false, false, null);channel.queueBind(deadQueue, DEAD_EXCHANGE, "lisi");System.out.println("等待接收死信消息........... ");DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");System.out.println("Consumer02 接收到消息" + message);};channel.basicConsume(deadQueue, true, deliverCallback, consumerTag -> {});}
}

(6)测试效果2:

启动消费者2

在这里插入图片描述

在这里插入图片描述

死信之最大长度

①生产者和消费者删除掉TTL的代码

②在消费者1中设置正常队列的长度限制

在这里插入图片描述

//设置正常队列的长度限制,例如发10个,4个则为死信
params.put("x-max-length",6);

注:先把原来生成的队列删除,因为条件参数发生变化了,已不再是同一个了,否则会报错

测试效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

死信之消息被拒

先注释掉最大长度的代码,然后,将消息都接收完,才可以继续发消息,还有删掉之前创建的最长时间TTL和最大长度的队列,以免对测试造成影响。

在这里插入图片描述

public class Consumer01 {//普通交换机名称private static final String NORMAL_EXCHANGE = "normal_exchange";//死信交换机名称private static final String DEAD_EXCHANGE = "dead_exchange";public static void main(String[] args) throws Exception {Channel channel = RabbitMqUtils.getChannel();//声明死信和普通交换机 类型为 directchannel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);channel.exchangeDeclare(DEAD_EXCHANGE, BuiltinExchangeType.DIRECT);//声明死信队列String deadQueue = "dead-queue";channel.queueDeclare(deadQueue, false, false, false, null);//死信队列绑定:队列、交换机、路由键(routingKey)channel.queueBind(deadQueue, DEAD_EXCHANGE, "lisi");//正常队列绑定死信队列信息Map<String, Object> params = new HashMap<>();//正常队列设置死信交换机 参数 key 是固定值params.put("x-dead-letter-exchange", DEAD_EXCHANGE);//正常队列设置死信 routing-key 参数 key 是固定值params.put("x-dead-letter-routing-key", "lisi");
//        //设置正常队列的长度限制,例如发10个,4个则为死信
//        params.put("x-max-length",6);//正常队列String normalQueue = "normal-queue";channel.queueDeclare(normalQueue, false, false, false, params);channel.queueBind(normalQueue, NORMAL_EXCHANGE, "zhangsan");System.out.println("等待接收消息........... ");DeliverCallback deliverCallback = (consumerTag, delivery) -> {String message = new String(delivery.getBody(), "UTF-8");if (message.equals("info5")) {System.out.println("Consumer01 接收到消息" + message + "并拒绝签收该消息");//requeue 设置为 false 代表拒绝重新入队 该队列如果配置了死信交换机将发送到死信队列中channel.basicReject(delivery.getEnvelope().getDeliveryTag(), false);} else {System.out.println("Consumer01 接收到消息" + message);channel.basicAck(delivery.getEnvelope().getDeliveryTag(), false);}};//开启手动应答channel.basicConsume(normalQueue, false, deliverCallback, consumerTag -> {});}}

测试效果:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

消息队列-RabbitMQ:死信队列 到此完结,笔者归纳、创作不易,大佬们给个3连再起飞吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/694661.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

postgres

1.下载postgres 解压后 bin\initdb -D data -U postgres -A password -E utf8 -W // 初始化设置密码这里的账号是postgres pg_ctl.exe register -N "PostgreSQL" -D "F:/pgsql/data" //windows 本地生成服务 pg_ctl -D F:/pgsql/data -l F:/pgsql/logs/pg…

用idea debug时,怎么在某个map对象中再加个key value

实现方式 在用idea 进行 debug时&#xff0c;我们经常喜欢对某行代码打断点&#xff0c;然后对某个对象重新设置值&#xff0c;以快速地实现我们预期想覆盖的场景。通常的方式是用鼠标右键点击某个对象&#xff0c;然后选择Set value进行设置值&#xff0c;但是如果想在map中添…

鸿蒙原生应用元服务实战-发布时多设备选择注意事项

在可公开可获取DevEco Studio最新版本&#xff0c;Stage模型ArkTSAPI9开发元服务HarmonyOS4现不支持平板等;但是元服务在发布时是可选平板、智慧屏电视设备发布。 如果开发人员与上架运营人员沟通不充分的话&#xff0c;上架运营人员可能会选择多设备发布&#xff0c;试一试&am…

bugku3

xxx二手交易市场 进去是这样讴歌乱进的页面 查看了一下源代码也没什么 先随便注册一个账号 然后登录 随便看了看&#xff0c;发现可以修改头像 上传文件 随便上传了一个图片 发现他对图片进行了base64加密 解密后得到是 data:image/jpeg;base64 这里重新修改类型为php&a…

【buuctf--我有一只马里奥】

这是一道关于 ntfs 流查看的题目运行 exe 后会出来一个 1.txt 文件 在 exe 和 1.txt 文件目录下打开终端&#xff0c;输入 notepad 1.txt:flag.txt就可以看到答案了。 这么做的原因见BUUCTF misc 专题&#xff08;53&#xff09;[SWPU2019]我有一只马里奥_ntfs flag.txt 马里…

OpenAI新推出的Sora是什么?如何注册使用?

2024年2月16号&#xff0c;OpenAI全新发布文本视频模型Sora&#xff0c;可以通过指令生成特定的视频内容&#xff0c;这对于内容营销、广告宣传、教育教学等行业都将来带来巨大的机遇与挑战。 相信许多人跟小编一样&#xff0c;对此新兴产品跃跃欲试&#xff0c;那么应该如何注…

柔顺控制笔记

参资料&#xff1a; 【1】https://zhuanlan.zhihu.com/p/620918453 【2】https://blog.csdn.net/a735148617/article/details/108564836 【3】https://zhuanlan.zhihu.com/p/126338809 【4】机器人与环境间力_位置控制技术研究与应用_李正义 【5】水下机械臂建模及柔顺控制方法…

编程笔记 Golang基础 014 数据类型概述

编程笔记 Golang基础 014 数据类型概述 一、基本数据类型二、复合数据类型三、引用类型四、特殊类型小结 Go 语言的数据类型系统涵盖了基本数据类型、复合数据类型以及引用类型。 下面将对这些类型进行详细说明&#xff1a; 一、基本数据类型 布尔型 (bool)&#xff1a;表示逻…

Javascript中var和let之间的区别

文章目录 一.变量提升(声)二.let和var的区别 区别&#xff1a; 1、var有变量提升&#xff0c;而let没有&#xff1b; 2、let不允许在相同的作用域下重复声明&#xff0c;而var允许&#xff1b; 3、let没有暂时性死区问题&#xff1b; 4、let创建的全局变量没有给window设置对应…

不同种类遥感图像汇总 !!

文章目录 前言 1、可见光遥感图像 2、全色遥感图像 3、多光谱遥感图像 4、高光谱遥感图像 5、红外遥感图像 6、激光雷达图像 7、合成孔径雷达遥感图像 前言 遥感技术是从远距离感知目标反射或自身辐射的电磁波、可见光、红外线&#xff0c;对目标进行探测和识别的技术。遥感卫…

懒汉单例设计模式与饿汉单例设计模式

单例模式即一个类确保只有一个对象,主要用于避免浪费内存 1.饿汉单例设计模式:拿到对象时,对象就早已经创建好了 public class A { private static A a new A(); private A(){ } public static A getObject(){ return a;} } 写法: 把类的构造器私有 在类中自己创建一个对…

【IOS】oc中property属性值详解

1. atomic与nonatomic atomic&#xff1a;原子属性确保属性的读取和写入操作在多线程环境中是线程安全的。这意味着&#xff0c;当一个线程正在读取或写入属性时&#xff0c;其他线程不能同时访问该属性。虽然这提供了线程安全性&#xff0c;但它也引入了性能开销&#xff0c;…

【JAVA高级面试题】运用锁机制实现一个自定义的阻塞队列

文章目录 前言实战演示写在最后 前言 前几天看见一个高级Java面试题&#xff0c;我觉得很有代表意义。既考察了面试者的基本锁机制运用&#xff0c;也了解了阻塞队列的产生实现原理。先分享出来&#xff0c;以供鉴赏。 面试题&#xff1a;实现一个自定义的阻塞队列&#xff0c…

java面试题之spring篇

1.Spring是什么&#xff1f;作用是什么&#xff1f; Spring是一个轻量级的JavaEE框架&#xff0c;它主要解决企业应用中的复杂性问题。Spring框架有三个核心部分&#xff1a;IoC容器、AOP和数据访问/集成层。Spring中的IoC容器提供了一种对象创建和对象之间关系管理的机制&…

Json简介与基本使用

一、JSON简介 JavaScript Object Notation (JSON) 是一种将对象转换为字符串的格式&#xff0c;这种格式易于阅读和编写&#xff0c;同时也易于机器解析和生成。JSON对象的语法格式与JavaScript对象的基本一致&#xff0c;但有所不同&#xff0c;例如JSON中的属性名需加双引号…

React 事件处理 ( this问题 参数传递 ref)

React事件的命名采用小驼峰方式&#xff08;cameCase&#xff09;,而不是小写 使用JSX语法时你需要传入一个函数作为事件处理函数&#xff0c;而不是一个字符串 你不能通过返回false 的方式阻止默认行为。你必须显示式的使用preventDefault 1 this 需要谨慎对待JSX回调函数中的…

Linux的Ubuntu的APT使用

Linux的Ubuntu的APT使用 apt 介绍 apt 是 Advanced Packaging Tool 的简称&#xff0c;是一款安装包管理工具。在 Ubuntu 下&#xff0c;我们可以使用 apt 命令进行软件包的安装、删除、清理等&#xff0c;类似于 Windows 中的软件管理工具。 Ubuntu 软件操作的相关命令 su…

Android 面试问题 2024 版(其二)

Android 面试问题 2024 版&#xff08;其二&#xff09; 六、多线程和并发七、性能优化八、测试九、安全十、Material设计和 **UX/UI** 六、多线程和并发 Android 中的进程和线程有什么区别&#xff1f; 答&#xff1a;进程是在自己的内存空间中运行的应用程序的单独实例&…

MySQL的多种约束

事实上&#xff0c;写入表的数据只有数据类型上的约束&#xff0c;但是没有其他更为严格为约束&#xff08;例如 48.2kg 中的 48.2 填在体重字段里是符合浮点类型的约束的&#xff0c;但是万一该数据填入到另外一个身高字段里呢&#xff1f;&#xff09;&#xff0c;就有可能导…

Maven的下载安装配置教程

一、简单了解一下什么是Maven Maven就是一款帮助程序员构建项目的工具&#xff0c;我们只需要告诉Maven需要哪些Jar 包&#xff0c;它会帮助我们下载所有的Jar&#xff0c;极大提升开发效率。 1.Maven翻译为“专家“&#xff0c; ”内行”的意思&#xff0c;是著名Apache公司下…