RabbitMQ 之 死信队列

目录

​编辑一、死信的概念

二、死信的来源

三、死信实战

1、代码架构图

2、消息 TTL 过期

(1)消费者

(2)生产者

(3)结果展示​编辑

 3、队列达到最大长度

(1)消费者

(2)生产者

(3)结果展示

4、消息被拒

(1)消费者

(2)生产者

(3)结果展示


一、死信的概念

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

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


二、死信的来源

1、消息 TTL 过期
2、队列达到最大长度(队列满了,无法再添加数据到 mq 中)
3、消息被拒绝(basic.reject 或 basic.nack)并且 requeue=false.


三、死信实战

1、代码架构图

生产者正常情况下走的是普通的交换机,这个交换机的类型是 direct ,它和普通队列之间的关系是一个叫 "zhangsan" 的路由 key, 正常情况下会被 C1 消费。

但是发生了上面所说的三种情况中的一种,成为了死信,然后被转换到死信交换机中,这个死信交换机也是 direct 类型,它们之间的 routingKey 是 "lisi",然后就进入了死信队列,死信队列由  C2 消费。


2、消息 TTL 过期

(1)消费者

// 死信队列 实战
// 消费者 1
public class Comsumer01 {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    // 死信交换机名称
    public static final String DEAD_EXCHANGE = "dead_exchange";
    // 普通队列名称
    public static final String NORMAL_QUEUE = "normal_queue";
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        // 交换机的声明
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE,BuiltinExchangeType.DIRECT);

        // 普通队列的声明
        Map<String, Object> arguments = new HashMap<>();
        // 过期时间
        //arguments.put("x-message-ttl",100000);
        // 正常队列设置死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        // 设置死信 RoutingKey
        arguments.put("x-dead-letter-routing-key","lisi");
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,arguments);
        
        
        // 死信队列的声明
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
        // 绑定普通的交换机与普通队列
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        // 绑定死信的交换机与死信的队列
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            System.out.println("Consumer01 接收的消息是: " + new String(message.getBody(),"UTF-8"));
        };

        CancelCallback cancelCallback = consumerTag->{};

        channel.basicConsume(NORMAL_QUEUE,true,deliverCallback,cancelCallback);
    }
}

// 消费者 2
public class Comsumer02 {
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            System.out.println("Consumer02 接收的消息是: " + new String(message.getBody(),"UTF-8"));
        };
        CancelCallback cancelCallback = consumerTag->{};
        
        channel.basicConsume(DEAD_QUEUE,true,deliverCallback,cancelCallback);
    }
}

(2)生产者

// 死信队列  生产者代码
public class Producer {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtils.getChannel();
        // 死信消息 设置 TTL 的时间
        AMQP.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());

        }
    }
}

(3)结果展示


 3、队列达到最大长度

(1)消费者

// 死信队列 实战
// 消费者 1
public class Comsumer01 {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    // 死信交换机名称
    public static final String DEAD_EXCHANGE = "dead_exchange";
    // 普通队列名称
    public static final String NORMAL_QUEUE = "normal_queue";
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        // 交换机的声明
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE,BuiltinExchangeType.DIRECT);

        // 普通队列的声明
        Map<String, Object> arguments = new HashMap<>();
        // 过期时间
        //arguments.put("x-message-ttl",100000);
        // 正常队列设置死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        // 设置死信 RoutingKey
        arguments.put("x-dead-letter-routing-key","lisi");
        // 设置正常队列的长度的限制
        arguments.put("x-max-length",6);
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,arguments);


        // 死信队列的声明
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
        // 绑定普通的交换机与普通队列
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        // 绑定死信的交换机与死信的队列
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            System.out.println("Consumer01 接收的消息是: " + new String(message.getBody(),"UTF-8"));
        };

        CancelCallback cancelCallback = consumerTag->{};

        channel.basicConsume(NORMAL_QUEUE,true,deliverCallback,cancelCallback);
    }
}
// 死信队列 实战
// 消费者 2
public class Comsumer02 {
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            System.out.println("Consumer02 接收的消息是: " + new String(message.getBody(),"UTF-8"));
        };
        CancelCallback cancelCallback = consumerTag->{};

        channel.basicConsume(DEAD_QUEUE,true,deliverCallback,cancelCallback);
    }
}

(2)生产者

// 死信队列  生产者代码
public class Producer {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtils.getChannel();
        // 死信消息 设置 TTL 的时间
        /*AMQP.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",null,message.getBytes());

        }
    }
}

(3)结果展示


4、消息被拒

(1)消费者

// 死信队列 实战
// 消费者 1
public class Comsumer01 {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";
    // 死信交换机名称
    public static final String DEAD_EXCHANGE = "dead_exchange";
    // 普通队列名称
    public static final String NORMAL_QUEUE = "normal_queue";
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        // 交换机的声明
        channel.exchangeDeclare(NORMAL_EXCHANGE, BuiltinExchangeType.DIRECT);
        channel.exchangeDeclare(DEAD_EXCHANGE,BuiltinExchangeType.DIRECT);

        // 普通队列的声明
        Map<String, Object> arguments = new HashMap<>();
        // 过期时间
        //arguments.put("x-message-ttl",100000);
        // 正常队列设置死信交换机
        arguments.put("x-dead-letter-exchange",DEAD_EXCHANGE);
        // 设置死信 RoutingKey
        arguments.put("x-dead-letter-routing-key","lisi");
        // 设置正常队列的长度的限制
        // arguments.put("x-max-length",6);
        channel.queueDeclare(NORMAL_QUEUE,false,false,false,arguments);


        // 死信队列的声明
        channel.queueDeclare(DEAD_QUEUE,false,false,false,null);
        // 绑定普通的交换机与普通队列
        channel.queueBind(NORMAL_QUEUE,NORMAL_EXCHANGE,"zhangsan");
        // 绑定死信的交换机与死信的队列
        channel.queueBind(DEAD_QUEUE,DEAD_EXCHANGE,"lisi");

        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            String msg = new String(message.getBody(),"UTF-8");
            if (msg.equals("info5")){
                System.out.println("Consumer01 接收的消息是: " + msg + ": 此消息是被 C1 拒绝的");
                // 拒绝,且不放囧普通队列
                channel.basicReject(message.getEnvelope().getDeliveryTag(),false);
            }else {
                System.out.println("Consumer01 接收的消息是: " + new String(message.getBody(),"UTF-8"));   
                channel.basicAck(message.getEnvelope().getDeliveryTag(),false);            
            }
        };

        CancelCallback cancelCallback = consumerTag->{};

        // 开启手动应答
        channel.basicConsume(NORMAL_QUEUE,false,deliverCallback,cancelCallback);
    }
}
// 死信队列 实战
// 消费者 2
public class Comsumer02 {
    // 死信队列名称
    public static final String DEAD_QUEUE = "dead_queue";

    public static void main(String[] args) throws IOException, TimeoutException {

        Channel channel = RabbitMqUtils.getChannel();
        System.out.println("等待接收消息.....");

        DeliverCallback deliverCallback = ( consumerTag, message) ->{
            System.out.println("Consumer02 接收的消息是: " + new String(message.getBody(),"UTF-8"));
        };
        CancelCallback cancelCallback = consumerTag->{};

        channel.basicConsume(DEAD_QUEUE,true,deliverCallback,cancelCallback);
    }
}

(2)生产者

// 死信队列  生产者代码
public class Producer {
    // 普通交换机名称
    public static final String NORMAL_EXCHANGE = "normal_exchange";

    public static void main(String[] args) throws IOException, TimeoutException {
        Channel channel = RabbitMqUtils.getChannel();
        // 死信消息 设置 TTL 的时间
        /*AMQP.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",null,message.getBytes());

        }
    }
}

(3)结果展示

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

雷军-2022.8小米创业思考-8-和用户交朋友,非粉丝经济;性价比是最大的诚意;新媒体,直播离用户更近;用真诚打动朋友,脸皮厚点!

第八章 和用户交朋友 2005年&#xff0c;为了进一步推动金山的互联网转型&#xff0c;让金山的同事更好地理解互联网的精髓&#xff0c;我推动了一场向谷歌学习的运动&#xff0c;其中一个小要求就是要能背诵“谷歌十诫”。 十诫的第一条就令人印象深刻&#xff1a;以用户为中…

rfid资产管理系统如何帮助医院管理耗材的

RFID资产管理系统可以帮助医院管理耗材&#xff0c;提高耗材管理的效率和准确性。以下是它可以发挥作用的几个方面&#xff1a; 1. 实时跟踪和定位&#xff1a;使用RFID标签附加在耗材上&#xff0c;可以实时跟踪和定位耗材的位置。医院可以通过系统查询耗材的实时位置&#xf…

“AI黏土人”一夜爆火,图像生成类应用应该如何长期留住用户?

文章目录 最近大火的“AI黏土人”&#xff0c;一股浓浓的《小羊肖恩》风。 凭借这这种搞怪的风格&#xff0c;“AI黏土人”等图像生成类应用凭借其创新技术和市场需求迅速崛起并获得巨大关注。然而&#xff0c;要保持用户黏性并确保长期发展&#xff0c;这些应用需要采取一系列…

Python爬虫项目实战:百度任意图片抓取

大家好&#xff0c;我是南枫&#xff0c;这篇文章我将给大家介绍如何使用Python爬虫来达到想爬哪个明星图片就能爬下来的效果&#xff0c;那我们接下来看看如何实现的吧。 导入Python的requests库和re库。requests库用于发送HTTP请求&#xff0c;而re库用于处理正则表达式。 通…

爬虫学习1

爬虫网站&#xff1a;All products | Books to Scrape - Sandbox 豆瓣网&#xff1a;豆瓣电影 Top 250 我们需要安装一个第三方库来解析爬取到的html内容&#xff0c;终端输入pip install bs4,安装成功后引入需要的模块 我们先爬取所有的价格 import requests from bs4 import…

数据结构-队列(带图详解)

目录 队列的概念 画图理解队列 代码图理解 代码展示(注意这个队列是单链表的结构实现) Queue.h(队列结构) Queue.c(函数/API实现) main.c(测试文件) 队列的概念 队列&#xff08;Queue&#xff09;是一种基础的数据结构&#xff0c;它遵循先进先出&#xff08;First In …

中兴通讯携手AIS,助力泰国5G通信事业发展

前不久&#xff0c;中兴通讯携手泰国领先的移动运营商AIS&#xff0c;于泰国曼谷A-Z中心宣布商用部署中兴通讯最新一代的无线先锋产品。双方通力合作&#xff0c;将构建一个绿色、极简的智能5G通信网络&#xff0c;助力泰国5G通信事业发展。    新一代Super-N技术&#xff0c…

【R语言】获取任意颜色的HTML 颜色代码、十六进制颜色代码、 RGB代码

网站来源&#xff1a; https://htmlcolorcodes.com/ 界面如下所示&#xff1a; 通过鼠标任意选择不同的颜色&#xff0c;就能获取该色的十六进制代码、RGB代码等。 除此之外&#xff0c;还提供了一些常用颜色的便捷选项,如下&#xff1a; 任意选择一种颜色&#xff0c;即可出…

5月27日

思维导图 #include <iostream>using namespace std; namespace st_open {string a1;string retval(string a1);} using namespace st_open; int main() {getline(cin,a1);cout << "逆置前的字符串&#xff1a;" << a1 << endl;a1rerval(a1);…

心电信号降噪方法(滤波器/移动平均/小波等,MATLAB环境)

对于一个正常的、完整的心动周期&#xff0c;对应的心电图波形如下图所示&#xff0c;各个波形都对应着心脏兴奋活动的生理过程&#xff0c;包含P波&#xff0c;PR段&#xff0c;QRS波群&#xff0c;ST段&#xff0c;T波&#xff0c;U波。 &#xff08;1&#xff09;P波心电图中…

Python3 笔记:Python之禅

打开Python Shell&#xff0c;输入import this&#xff0c;按回车键运行程序。 Beautiful is better than ugly. 优雅胜于丑陋。 Explicit is better than implicit. 明确胜于含糊。 Simple is better than complex. 简单胜于复杂。

ThingsBoard网关在燃气泄漏监测中的应用

据不完全统计&#xff0c;全国城市燃气企业的供销差率大约在3%~4%&#xff0c;也就意味着越多的天然气销量就有越多的天然气损失。城市燃气企业计量管理已经接近最不利的状态&#xff0c;开展有效的计量管理势在必行。 智慧燃气综合管理系统 在燃气管网中部署智能传感器、数据采…

Centos 7 安装刻录至服务器

前言 在日常测试中&#xff0c;会遇到很多安装的场景&#xff0c;今天给大家讲一下centos 7 的安装&#xff0c;希望对大家有所帮助。 一.下载镜像 地址如下&#xff1a; centos官方镜像下载地址https://www.centos.org/download/ 按照需求依次点击下载 二.镜像刻录 镜像刻…

linux centos磁盘清理相关

清理磁盘流程 1、查看磁盘挂载路径及使用率 df -h2、查看当前文件下文件大小 du -sh *3、制空文件内容 > 文件名 ###制空当前文件内容&#xff0c;直接清0 列子 >access.loglinux操作系统中&#xff0c;经常会遇到磁盘空间满的问题。遇到这样的问题&#xff0c;先查下…

海外仓erp系统是什么?和海外仓管理系统一样吗?

为了满足海外仓全球化发展的大趋势&#xff0c;同时提升海外仓运转的效率&#xff0c;一套好用&#xff0c;性价比高的海外仓管理系统还是非常重要的。 不过很多海外仓企业其实不太分得清erp系统和海外仓管理系统的差异&#xff0c;今天我们就来系统的聊一下&#xff0c;方便大…

5.27周报

这两周邻近毕业故没有很多时间来学习课余内容&#xff0c;另外最近身体有些不舒服【偏头痛】&#xff0c;所以学的内容不多&#xff0c;包括SVM向量机和ResNet【不包括代码复现】 1.SVM支持向量机的大概内容 1、目的&#xff1a; 主要内容是如何找到分类的那条线【超平面】—…

二叉搜索树与双向链表(C++)

文章目录 1. 题目描述2.题目解析 题目来源&#xff1a; 牛客网…二叉搜索树与双向链表 1. 题目描述 输入一棵二叉搜索树&#xff0c;将该二叉搜索树转换成一个排序的双向链表。如下图所示 数据范围&#xff1a;输入二叉树的节点数 0≤n≤1000&#xff0c;二叉树中每个节点的值…

函数调用时长的关键点:揭秘参数位置的秘密

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、默认参数的秘密 示例代码 二、关键字参数与位置参数的舞蹈 示例代码 总结 一、默认参…

一键开关机电路

大家好&#xff0c;我是记得诚。 球友问了一个问题&#xff0c;是这样的。 诚哥&#xff0c;请教一个问题。这个一键开关机有没有问题&#xff0c;或者有哪些改进的地方。 1、内部电源供电&#xff0c;可外接适配器。 2、VBAT接锂电池&#xff0c;VBUS接电源适配器。 3、BU…

Spring:IoC容器(基于注解管理bean)

1. HelloWorld * 引入依赖* 开启组件扫描* 使用注解定义 Bean* 依赖注入 2.开启组件扫描 <?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframework.org/schema/beans"xmlns:xsi"http://www.w3.org/20…