[MQ] 死信队列介绍与场景描述

news2024/10/7 8:31:55

✨✨个人主页:沫洺的主页

📚📚系列专栏: 📖 JavaWeb专栏📖 JavaSE专栏 📖 Java基础专栏📖vue3专栏 

                           📖MyBatis专栏📖Spring专栏📖SpringMVC专栏📖SpringBoot专栏

                           📖Docker专栏📖Reids专栏📖MQ专栏📖SpringCloud专栏     

💖💖如果文章对你有所帮助请留下三连✨✨

🐣什么是死信

在 RabbitMQ 中充当主角的就是消息,在不同场景下,消息会有不同地表现。

死信就是消息在特定场景下的一种表现形式,这些场景包括:

  1. 消息被拒绝访问,即 RabbitMQ返回 basicNack 的信号时。 或者拒绝basicReject
  2. 消费者发生异常,超过重试次数 。
  3. 消息的 TTL 时间过期。
  4. 消息队列达到最大长度。

上述场景经常产生死信,即消息在这些场景中时,被称为死信。

🐤什么是死信队列 

死信队列就是用于储存死信的消息队列,在死信队列中,有且只有死信构成,不会存在其余类型的消息。

死信队列在 RabbitMQ 中并不会单独存在,往往死信队列都会绑定这一个普通的消息队列,当所绑定的消息队列中,有消息变成死信了,那么这个消息就会重新被交换机路由到指定的死信队列中去,我们可以通过对这个死信队列进行监听,从而手动的去对这一消息进行补偿。

🐓使用死信队列

死信队列基本使用,只需要在声明业务队列的时候,绑定指定的死信交换机和RoutingKey即可。

    //定义业务队列
    @Bean
    public Queue directQueue() {
        return QueueBuilder.durable(QNAME)
                .deadLetterExchange(DENAME) //通过这两个配置,使我们的业务队列与死信交换机有关系了
                .deadLetterRoutingKey(DKEY)
                .ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理
                .maxLength(1000) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理
                .build();
    }

环境搭建

消费者

@Component
public class DeadConsumer {
    //死信
    private static final String DENAME = "211-DeadExchage-死信";
    private static final String DQNAME = "211-DeadQueue-死信";
    private static final String DKEY = "211-DeadQueue-RoutingKey";
    //业务
    private static final String ENAME = "211-DirectExchage-业务";
    private static final String QNAME = "211-DirectQueue-业务";
    private static final String KEY = "211-DirectQueue-RoutingKey";

    //region  队列和交换机的注册
    //定义死信交换机,本质就是普通的直连交换机
    @Bean
    public DirectExchange deadExchange() {
        return new DirectExchange(DENAME, true, false);
    }

    //定义死信队列
    @Bean
    public Queue deadQueue() {
        return QueueBuilder.durable(DQNAME).build();
    }

    //创建死信队列和死信交换机的绑定关系
    @Bean
    public Binding binding1() {
        return BindingBuilder.bind(deadQueue()).to(deadExchange()).with(DKEY);
    }

    //定义业务交换机
    @Bean
    public DirectExchange directExchange() {
        return new DirectExchange(ENAME, true, false);
    }

    //定义业务队列
    @Bean
    public Queue directQueue() {
        return QueueBuilder.durable(QNAME)
                .deadLetterExchange(DENAME) //通过这两个配置,使我们的业务队列与死信交换机有关系了
                .deadLetterRoutingKey(DKEY)
                .ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理
                .maxLength(5) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理
                .build();
    }

    //创建业务队列和业务交换机的绑定关系
    @Bean
    public Binding binding2() {
        return BindingBuilder.bind(directQueue()).to(directExchange()).with(KEY);
    }

    //endregion

    //业务消费者
    @RabbitHandler
    @RabbitListener(queues = QNAME)
    public void process1(UserRegisterOk userRegisterOk) {
        System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")
                +"消费者接收消息:" + userRegisterOk.getName()
                + "," + userRegisterOk.getAge());
    }
}

生产者

@Component
public class DeadProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(){
        UserRegisterOk userRegisterOk1 = UserRegisterOk.builder().name("张三").age(18).build();
        //要将对象序列化,转成字符串,使用消息转换器MessageConverter
        rabbitTemplate.convertAndSend(
                "211-DirectExchage-业务",
                "211-DirectQueue-RoutingKey",
                 userRegisterOk1);
        System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") +"生产者生产消息-->张三发送成功");

    }
}

启动类

@SpringBootApplication
public class App4 {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(App4.class, args);
        DeadProducer producer = context.getBean(DeadProducer.class);
        producer.sendMessage();
    }
}

场景描述: 当没有消费者时,消息的 TTL 时间过期

ttl(60*1000) //设置消息多久过期,消息超过这个时间就直接给死信交换机,让它处理

死信队列一般是没有消费者的,都是通过人工干预去处理

场景描述: 没有消费者时,消息队列达到最大长度

 生产者发送8条消息,消息队列最大长度为5,多出的3条会放到死信队列里

 maxLength(5) //设置队列最大容量,超过这个容量就直接给死信交换机,让它处理

场景描述: 手动应答下,消息被拒绝访问

#开启消费者应答模式为 auto自动应答 manual手动应答
spring.rabbitmq.listener.simple.acknowledge-mode=manual
#开启消费者自动重试机制,也就是消费者函数只要抛出异常,就会触发重试
spring.rabbitmq.listener.simple.retry.enabled=false

还是生产者发送8条消息,区别是对象年龄不同

@Component
public class DeadProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void sendMessage(){
        for (int i=1;i<=8;i++){
            UserRegisterOk userRegisterOk1 = UserRegisterOk.builder().name("张三").age(18+i).build();
            //要将对象序列化,转成字符串,使用消息转换器MessageConverter
            rabbitTemplate.convertAndSend(
                    "211-DirectExchage-业务",
                    "211-DirectQueue-RoutingKey",
                    userRegisterOk1);
            System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") +"生产者生产消息-->张三发送成功");
        }
    }
}

消费者判断对象的年龄,符合就应答,不符合就拒绝应答

    //业务消费者
    @RabbitHandler
    @RabbitListener(queues = QNAME)
    public void process1(UserRegisterOk userRegisterOk,Message message, Channel channel) throws IOException {
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        if(userRegisterOk.getAge()>23){
            System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")
                    +"消费者接收消息:" + userRegisterOk.getName()
                    + "," + userRegisterOk.getAge()+"年龄符合");
            channel.basicAck(deliveryTag,false);
        }else {
            System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss")
                    +"消费者接收消息:" + userRegisterOk.getName()
                    + "," + userRegisterOk.getAge()+"年龄不符合");
            channel.basicNack(deliveryTag,false,false);
        }
    }

场景描述: 消费者发生异常,超过重试次数

重试5次

#开启消费者应答模式为 auto自动应答 manual手动应答
spring.rabbitmq.listener.simple.acknowledge-mode=auto
#开启消费者自动重试机制,也就是消费者函数只要抛出异常,就会触发重试
spring.rabbitmq.listener.simple.retry.enabled=true
#设置重试最大次数
spring.rabbitmq.listener.simple.retry.max-attempts=5
#设置重试时间最大间隔
spring.rabbitmq.listener.simple.retry.max-interval=8000ms
#设置重试时间间隔
spring.rabbitmq.listener.simple.retry.initial-interval=1000ms
#设置重试时间间隔的倍数
spring.rabbitmq.listener.simple.retry.multiplier=2

模拟消费者异常

    //业务消费者
    @RabbitHandler
    @RabbitListener(queues = QNAME)
    public void process1(UserRegisterOk userRegisterOk) {
            System.out.println(DateUtil.format(DateUtil.date(),"HH:mm:ss") 
                    +"消费者接收消息:" + userRegisterOk.getName()
                    + "," + userRegisterOk.getAge());
            int i=1/0;
    }

5次之后就不再消费了,将消息放到死信队列里

#超过重试次数后,进入死信队列,默认为false
#重试次数超过上面的设置之后是否丢弃(false不丢弃时需要写相应代码将该消息加入死信队列)
spring.rabbitmq.listener.simple.default-requeue-rejected = false

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

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

相关文章

Js逆向教程-11常见混淆AA和JJ

Js逆向教程-11常见混淆AA和JJ js默认 支持Unicode的。 所以支持所有的国家语种。 有没有哪些国家的和O很像但不是O,和0很像但不是0,和p很像但不是p 所以可以用这个相近的符号进行代码混淆。 var O00OO,o00oo;一、AA混淆和OO混淆 https://www.sojson.com/aaencode.html 这个…

Docker guide

前言 docker学习记录&#xff0c;内容参考 Docker Training Course for the Absolute Beginner Basic Command docker pull <Image:只是下载image&#xff0c;不会运行docker run <Image>:启动image实例&#xff0c;如果image不在docker host上&#xff0c;docker会…

【长难句分析精讲】状语从句

1. 状语从句九大类 时间状语从句&#xff1a;after / before / when / while / as / since / once / until地点状语从句&#xff1a;where原因状语从句&#xff1a;because / as / for / since让步状语从句&#xff1a;though / although / even if even though / while / as…

[Spring Cloud] Eureka Server安装

✨✨个人主页:沫洺的主页 &#x1f4da;&#x1f4da;系列专栏: &#x1f4d6; JavaWeb专栏&#x1f4d6; JavaSE专栏 &#x1f4d6; Java基础专栏&#x1f4d6;vue3专栏 &#x1f4d6;MyBatis专栏&#x1f4d6;Spring专栏&#x1f4d6;SpringMVC专栏&#x1f4d6;SpringBoot专…

ARM仿真器J-Link灯不亮的解决办法

感慨&#xff1a; 网络世界真是越来越封闭了啊&#xff0c;下载东西越来越难。 解决问题会越来越难。 解决仿真器Jlink灯不亮这个问题用了一下午..... 步骤&#xff1a; &#xff08;弯路&#xff1a;windows安装AT91-ISP&#xff0c;发现SAM_PROG v2.4加载bin后不能点击Write…

Android Camera性能分析 第23讲 录像Buffer Path实战和Trace分析

​ 本讲是Android Camera性能分析专题的第23讲&#xff0c;我们介绍录像Buffer Path实战和Trace分析&#xff0c;包括如下内容&#xff1a; Video Codec MediaRecorder.getSurface录像Buffer Path Trace分析Video Codec2 MediaRecorder.getSurface录像Buffer Path Trace分析…

java计算机毕业设计组成原理教学网站(附源码、数据库)

java计算机毕业设计组成原理教学网站&#xff08;附源码、数据库&#xff09; 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项…

手把手教你搭建K8S集群

搭建前提条件&#xff1a;VMare16pro CentOS-7-x86_64-DVD-2009.iso镜像文件&#xff0c; 远程连接工具Xshell或者MobaXterm 首先创建三台centos7的虚拟机&#xff0c;装虚拟机的话大家可以参照网上资料&#xff0c;非常容易。 使用 kubeadm 安装 Kubernetes 集群 1&#…

通关算法题之 ⌈二叉树⌋ 下

填充每个节点的下一个右侧节点指针 116、填充每个节点的下一个右侧节点指针 给定一个 完美二叉树 &#xff0c;其所有叶子节点都在同一层&#xff0c;每个父节点都有两个子节点。二叉树定义如下&#xff1a; struct Node {int val;Node *left;Node *right;Node *next; }填充…

手机短信注册验证与登录功能

文章目录一、前言二、准备工作三、发布短信1、基本测试发布①可-使用测试模板进行调试②测试结果③注意&#xff0c;可能会调试失败&#xff0c;是因为没有余额。进入首页点击头像>进入余额充值&#xff1b;一条大概4分钱④创建SpringBoot项目demo2、可自定义模板&#xff0…

[acwing周赛复盘] 第 78 场周赛20221119

[acwing周赛复盘] 第 78 场周赛20221119 一、本周周赛总结二、4719. 商品种类1. 题目描述2. 思路分析3. 代码实现三、4720. 字符串1. 题目描述2. 思路分析3. 代码实现四、4721. 排队1. 题目描述2. 思路分析3. 代码实现六、参考链接一、本周周赛总结 这周蛮简单的。T2 栈的应用…

Kafka - Kafka应用场景|基础架构|Windows安装|命令行操作

文章目录1. 消息队列的应用场景2. 消息队列的两种模式3. Kafka 的基础架构4. Kafka 的安装5. Kafka 命令行操作1. 主题命令行操作2. 生产者命令行操作3. 消费者命令行操作1. 消息队列的应用场景 传统的消息队列的主要应用场景包括&#xff1a;缓存/消峰、解耦和异步通信。 ①…

Packet Tracer - 配置多区域 OSPFv3

地址分配表 设备 接口 IPv6 地址 OSPF 区域 RA G0/0 2001:DB8:1:A1::1/64 1 G0/1 2001:DB8:1:A2::1/64 1 S0/0/0 2001:DB8:1:AB::2/64 0 本地链路 FE80::A 不适用 RB G0/0 2001:DB8:1:B1::1/64 0 S0/0/0 2001:DB8:1:AB::1/64 0 S0/0/1 2001:DB8:1:BC:…

JVM运行时数据区域之PCRegister和虚拟机栈

运行时数据区域 Java 虚拟机在执行 Java 程序的过程中会把它所管理的内存划分为若干个不同的数据 区域。这些区域有各自的用途&#xff0c;以及创建和销毁的时间&#xff0c;有的区域随着虚拟机进程的启 动而一直存在&#xff0c;有些区域则是依赖用户线程的启动和结束而建立…

群晖NAS搭建WebDav服务,并内网穿透实现公网访问

WebDAV是基于HTTP协议的通信协议。适用于有些客户限制于其他协议&#xff0c;要求使用WebDAV协议进行数据传输的&#xff0c;下面是通过WebDAV协议来访问群晖NAS的设置教程。 1. 在群晖套件中心安装WebDav Server套件 点击打开套件中心&#xff0c;并搜索webdav&#xff0c;点…

性能测试-linux-top/vmstat/dstat命令,闭着眼睛也要背出来

目录 Linux系统差异化 Ubuntu安装应用 CentOS安装应用 Linux通用安装&#xff0c;tar.gz包 Linux系统帮助命令 help/man/info Linux系统中树状结构查看文件 Linux系统中文件类型区分与权限 Linux系统中都有哪些文件夹及其作用 Linux性能测试分析-TOP命令(重点) Linu…

NFV关键技术:DPDK技术栈在网络云中的最佳实践

本文篇幅有限&#xff0c;很难用短短几语就勾勒出DPDK的完整轮廓&#xff0c;概括来说&#xff0c;DPDK是一个技术栈&#xff0c;主要用于Intel架构的服务器领域&#xff0c;其主要目的就是提升x86标准服务器的转发性能。因此&#xff0c;本文只重点介绍DPDK平台部分技术在电信…

基于stm32单片机智能温控风扇控制系统Proteus仿真

资料编号&#xff1a;103 下面是相关功能视频演示&#xff1a; 103-基于stm32单片机智能温控风扇控制系统Proteus仿真&#xff08;源码仿真全套资料&#xff09;功能介绍&#xff1a;采用stm32单片机、ds18b20温度传感器采集温度&#xff0c;通过判断当前的温度值是否超过预设…

程序员怎样才能写出一篇好的博客或者技术文章?

文章目录来分享下鹅厂多位技术同学关于如何写好技术文章的经验。**1 为什么要写文章****1.1 对作者的好处****1.1.1 复盘学习成果&#xff0c;巩固知识理解****1.1.2 提升思考能力****1.1.3 传播技术知识&#xff0c;积累技术资产****1.1.4 提升表达与总结能力****1.1.5 打造个…

尚医通 (二十五) --------- 医院接口开发

目录一、医院系统模拟接口1. 服务部署2. 操作说明3. 上传接口与回调接口① 业务术语② 安全控制③ 业务接口④ 平台接口⑤ 医院接口二、集成 MongoDB三、添加医院基础类四、上传医院五、参数签名六、图片 Base64 编码七、查询医院接口一、医院系统模拟接口 1. 服务部署 ① 找…