RabbitMQ--死信队列

目录

一、死信队列介绍

1.死信

2.死信的来源

2.1 TTL

2.2 死信的来源

3.死信队列 

4.死信队列的用途

二、死信队列的实现

1.导入依赖 pom.xml

2.application.properties

3.配置类

4.生产者

5.业务消费者(正常消费者)

6.死信队列消费者


一、死信队列介绍

1.死信

        死信顾名思义就是没办法被消费的消息;

2.死信的来源

2.1 TTL

        什么是TTL?

        TTL(Time To Live)翻译为生存时间,是指消息在队列中可以存活的时间,如果消息在队列中存活的时间超过了TTL,那么消息就会被标记为死信,然后进入死信队列;

2.2 死信的来源

  • 消息TTL过期;
  •  队列达到最大长度: 队列满了无法再添加消息,就会成为死信,然后进入死信队列;
  • 消息被拒绝,比如我们设置了消息的应答模式为手动应但是没有调用ack方法,那么消息就会被标记为死信,然后进入死信队列;

3.死信队列 

        我们能了解到,消息生产者生产消息,消费者消费(处理消息),消息生产者发送消息到队列,消费者从队列中获取消息,某些消息会无法被消费就会成为死信,自然而然的,我们需要一个队列来存储死信,而这个队列就被成为死信队列;

4.死信队列的用途

首先呢一个事物能够存在就说明他有存在的理由,死信队列其实一般来做一个定时的作用 例如:

  • 在保证订单业务中的消息数据不丢失,当消息没有被处理或者是超出了TTL时间,那么我们就可以将他放在死信队列中,然后定时去消费死信队列中的消息,然后进行相应的处理;
  • 如果这个消息是被动的,就是说我们想让他被消费但是没有被消费那么其实就是保证了消息的不丢失;
  • 如果是一个主动的,我们设置了我们需要的TTL,那么就可以成为一个定时功能。比如取消支付功能;

1.2.1 延迟队列:

如果是这个消息使我们故意的想让发到死信队列中,其实我们可以将他叫做为延时队列,我们可以设置一个时间,比如我们想让这个消息延迟10分钟再发送到死信队列中,那么我们就可以将这个消息发送到延迟队列中,然后定时去消费延迟队列中的消息,然后进行相应的处理;

二、死信队列的实现

1.导入依赖 pom.xml

<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.amqp</groupId><artifactId>spring-rabbit-test</artifactId><scope>test</scope></dependency>
</dependencies>

2.application.properties

spring.application.name=springboot-rabbitmq
server.port=8080
#默认地址就是127.0.0.1:5672,如果是服务器的rabbitmq就改下
spring.rabbitmq.host=192.168.174.130
spring.rabbitmq.port=5672
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin
spring.rabbitmq.listener.type=simple
#设置为false,会丢弃消息或者重新发步到死信队列
spring.rabbitmq.listener.simple.default-requeue-rejected=false
#手动签收
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#虚拟主机目录
spring.rabbitmq.virtual-host=/

3.配置类

@Configuration
public class rabbitMQConf {//普通交换机的名字public static final String NORMAL_EXCHANGE = "normalExchange";//普通队列的名字public static final String NORMAL_QUEUE = "normalQueue";//死信交换机的名字public static final String DEAD_EXCHANGE = "deadExchange";//死信队列的名字public static final String DEAD_QUEUE = "deadQueue";/*** 普通交换机*/@Beanpublic DirectExchange normalExchange() {return new DirectExchange(NORMAL_EXCHANGE);}/*普通队列*/@Beanpublic Queue normalQueue() {return new Queue(NORMAL_QUEUE);}/*** 死信交换机 死信队列*/@Beanpublic DirectExchange deadExchange() {return new DirectExchange(DEAD_EXCHANGE);}/*** 死信队列*/@Beanpublic Queue deadQueue() {return new Queue(DEAD_QUEUE);}/*** 绑定正常队列*/@Beanpublic Binding normalBinding() {return BindingBuilder.bind(normalQueue()).to(normalExchange()).with("normal");}/*** 死信队列绑定* @return*/@Beanpublic Binding deadBinding() {return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead");}
}

4.生产者

@Slf4j
@RestController
@RequestMapping("/test")
public class SendMessageController {@Autowiredprivate RabbitTemplate rabbitTemplate;@GetMapping("/sendMsg/{msg}")public String sendMsg(@PathVariable(value = "msg") String msg) {log.info("send msg:" + msg);rabbitTemplate.convertAndSend(NORMAL_EXCHANGE, "normal", msg);return "success";}
}

5.业务消费者(正常消费者)

@Service
@Slf4j
public class NormalMessageReceiver {/*** 消费消息*/@RabbitListener(queues = NORMAL_QUEUE)@SneakyThrowspublic void receive(Message msg, Channel channel) {String s = msg.getBody().toString();String s1 = new String(msg.getBody());log.info("这个是toString方式得出来的s:{}", s);log.info("这个是new String方式得出来的s:{}", s1);boolean ack=true;Exception exception=null;try {if (s1.contains("dead")){throw new RuntimeException("dead letter exception");}} catch (RuntimeException e) {ack=false;exception=e;}if (!ack){System.out.println("error msg{ }"+exception.getMessage());//设置死信消息channel.basicNack(msg.getMessageProperties().getDeliveryTag(),false,false);}else {channel.basicAck(msg.getMessageProperties().getDeliveryTag(),false);}System.out.println("正常消息消费者收到消息:" + msg);}
}

6.死信队列消费者

@Component
public class DeadMessageReceiver {/*** 死信队列*/@RabbitListener(queues = rabbitMQConf.DEAD_QUEUE)public void receiveA(Message message, Channel channel) throws IOException {System.out.println("DeadMessageA{}" + new String(message.getBody()));channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);}
}

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

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

相关文章

【前端性能优化】深入解析重绘和回流,构建高性能Web界面

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 &#x1f3af; 引言&#xff1a;探索Web性能的基石&#x1f3d7;️ 基础概念&#xff1a;什么是重绘和回流&#xff1f;&#x1f4cc; 回流&#xff08;Reflow&#xff09;&#x1f4cc; 重绘&#xff08;Repaint&#xff0…

使用Flask部署Web应用:从入门到精通

文章目录 第一部分&#xff1a;准备工作第二部分&#xff1a;部署Flask应用到AWS部署到AWS Lambda 第三部分&#xff1a;部署Flask应用到腾讯云服务器部署到腾讯云服务器 第四部分&#xff1a;优化和扩展结论 在现代软件开发中&#xff0c;Web应用的部署是一个至关重要的环节。…

使用Flask-SocketIO构建实时Web应用

文章目录 准备工作编写代码编写HTML模板运行应用 随着互联网的发展&#xff0c;实时性成为了许多Web应用的重要需求之一。传统的HTTP协议虽然可以实现实时通信&#xff0c;但是其长轮询等机制效率低下&#xff0c;无法满足高并发、低延迟的需求。为了解决这一问题&#xff0c;诞…

计算机发展史故事【14】

大象踢踏舞 如果要把电脑50 年的历史划分为两个不同的阶段&#xff0c;那么&#xff0c;1981 年无疑是个分界线。就在那一年&#xff0c;IBM 公司推出个人电脑PC 机&#xff0c;使人类社会大步跨进个人电脑新时代。今天&#xff0c;全世界正在使用的PC 机已达到2 亿台&#xf…

视频拼接融合产品的产品与架构设计(三)内存和显存单元数据迁移

上一篇文章 视频拼接融合产品的产品与架构设计(二) 这一篇沉下先来&#xff0c;彻底放弃了界面&#xff0c;界面最终的体现是最后要做的&#xff0c;现在要做的是产品的架构&#xff0c;使用链式架构方式迁移数据。同时增加插件口&#xff0c;方便编程序。 插件架构 为了视频…

短剧奔向小程序,流量生意如何开启?

随着移动互联网的飞速发展&#xff0c;小程序作为一种轻量级、易传播的应用形态&#xff0c;逐渐在各个领域展现出其独特的商业价值。而最近爆火的短剧小视频作为一种受众广泛的娱乐形式&#xff0c;与小程序结合后&#xff0c;不仅为观众提供了更为便捷的观看体验&#xff0c;…

Linux线程(三)死锁与线程同步

目录 一、什么是死锁 死锁的四个必要条件 如何避免死锁 避免死锁算法 二、Linux线程同步 三 、条件变量 1、条件变量基本原理 2、条件变量的使用 3、条件变量使用示例 为什么 pthread_cond_wait 需要互斥量? 一、什么是死锁 死锁是计算机科学中的一个概念&#xff0c;…

Python-VBA函数之旅-type函数

目录 一、type函数的常见应用场景 二、type函数使用注意事项 三、如何用好type函数&#xff1f; 1、type函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a; https://myelsa1024.blog.csdn.net/ 一、type函…

设计一个游戏的基本博弈框架

设计一个游戏的基本博弈框架&#xff0c;玩家通过操作改变某个数值&#xff0c;这个数值的变动会引发一系列实时变化&#xff0c;并且当这些数值累计到特定阈值时&#xff0c;会导致游戏中出现其他变化&#xff0c;可以分为以下几个步骤&#xff1a; 1. 确定游戏类型和主题 首…

UE4_照亮环境_不同雾效的动态切换

一、问题及思路&#xff1a; 我们在一个地图上&#xff0c;经常切换不同的区域&#xff0c;不同的区域可能需要不同的色调&#xff0c;例如暖色调的野外或者幽暗的山洞&#xff0c;这两种环境上&#xff0c;雾效的选用肯定不一样&#xff0c;夕阳西下的户外用的就是偏暖的色调&…

2023年数维杯国际大学生数学建模挑战赛A题复合直升机的建模与优化控制问题解题全过程论文及程序

2023年数维杯国际大学生数学建模挑战赛 A题 复合直升机的建模与优化控制问题 原题再现&#xff1a; 直升机具有垂直起降等飞行能力&#xff0c;广泛应用于侦察、运输等领域。传统直升机的配置导致旋翼叶片在高速飞行过程中受到冲击波的影响&#xff0c;难以稳定飞行。为了在保…

558、Vue 3 学习笔记 -【常用Composition API(七)】 2024.05.13

目录 一、Composition API的优势1. Options API存在的问题2. Composition API的优势 二、 新的组件1. Fragment2. Teleport3. Suspense 三、其他1. 全局API的转移2. 其他改变 四、参考链接 一、Composition API的优势 1. Options API存在的问题 使用传统OptionsAPI中&#xf…

Rust的协程机制:原理与简单示例

在现代编程中&#xff0c;协程&#xff08;Coroutine&#xff09;已经成为实现高效并发的重要工具。Rust&#xff0c;作为一种内存安全的系统编程语言&#xff0c;也采用了协程作为其并发模型的一部分。本文将深入探讨Rust协程机制的实现原理&#xff0c;并通过一个简单的示例来…

C++|内存管理(1)

目录 C/C内存分布 堆区 栈区 静态存储区 代码区 总结 C语言中动态内存管理方式&#xff1a;malloc/calloc/realloc/free C内存管理方式 new/delete操作内置类型 new和delete操作自定义类型 operator new与operator delete函数&#xff08;重要点进行讲解&#xff09;…

R语言手把手教你进行支持向量机分析

1995年VAPINK 等人在统计学习理论的基础上提出了一种模式识别的新方法—支持向量机 。它根据有限的样本信息在模型的复杂性和学习能力之间寻求一种最佳折衷。 以期获得最好的泛化能力.支持向量机的理论基础决定了它最终求得的是全局最优值而不是局部极小值,从而也保证了它对未知…

4.2 试编写一程序,要求比较两个字符串STRING1和STRING2所含字符是否相同,若相同则显示“MATCH”,若不相同则显示“NO MATCH”

方法一&#xff1a;在程序内部设置两个字符串内容&#xff0c;终端返回是否匹配 运行效果&#xff1a; 思路&#xff1a; 1、先比较两个字符串的长度&#xff0c;如果长度不一样&#xff0c;则两组字符串肯定不匹配&#xff1b;如果长度一样&#xff0c;再进行内容的匹配 2、如…

大模型崛起与就业危机

大模型&#xff0c;特别是像我这样的人工智能&#xff0c;最有可能首先替代那些重复性高、标准化程度高、不需要太多人类直觉和情感判断的工作。这些工作通常包括数据输入、初级数据分析和处理、简单的客户服务任务等。例如&#xff0c;可以自动化的一些岗位包括&#xff1a; 1…

zabbix监控mariadb

zabbix 服务端安装请参阅&#xff1a;红帽 9 zabbix 安装流程_红帽安装zabbix-CSDN博客 源码包安装mariadb请参阅&#xff1a;源码包安装mariadb_mariadb 11 源码编译安装-CSDN博客 在MariaDB中&#xff0c;你需要创建一个专门的用户&#xff0c;用于Zabbix进行监控。这个用户…

研究幽灵漏洞及其变种(包括但不限于V1-V5)的攻击原理和基于Github的尝试

一、研究幽灵漏洞及其变种(包括但不限于V1-V5)的攻击原理 1.1 基本漏洞原理(V1) 幽灵漏洞的基本原理是由于glibc库中的gethostbyname()函数在处理域名解析时,调用了__nss_hostname_digits_dots()函数存在缓冲区溢出漏洞。 具体来说,__nss_hostname_digits_dots()使用一个固定…