RabbitMQ-死信队列常见用法

目录

一、什么是死信

 二、什么是死信队列 

​编辑 三、第一种情景:消息被拒绝时

四、第二种场景:. 消费者发生异常,超过重试次数 。 其实spring框架调用的就是 basicNack

五、第三种场景: 消息的Expiration 过期时长或队列TTL过期时间。

六、 第四种情景:  消息队列达到最大容量


一、什么是死信

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

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

1. 消息被拒绝访问,即 RabbitMQ返回 basicNack 的信号时 或者拒绝basicReject

2. 消费者发生异常,超过重试次数 。 其实spring框架调用的就是 basicNack

3. 消息的Expiration 过期时长或队列TTL过期时间

4. 消息队列达到最大容量

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

 二、什么是死信队列 

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

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

 三、第一种情景:消息被拒绝时

#设置消费者手动应答模式

spring.rabbitmq.listener.simple.acknowledge-mode = manual

package com.by.consumer;


import com.by.model.OrderingOk;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
@Slf4j
public class DeadConsumer {
    //死信交换机
    @Bean
    public DirectExchange deadExchange() {
        return ExchangeBuilder.directExchange("Dead_E01").build();
    }

    //死信队列
    @Bean
    public Queue deadQueue1() {
        return QueueBuilder.durable("Dead_Q01").build();
    }

    //死信交换机与死信队列的绑定
    @Bean
    public Binding deadBinding1(Queue deadQueue1, DirectExchange deadExchange) {
        return BindingBuilder.bind(deadQueue1).to(deadExchange).with("RK_DEAD");
    }

    //业务队列
    @Bean
    public Queue queue1() {
        return QueueBuilder
                .durable("Direct_Q01")
                .deadLetterExchange("Dead_E01")
                .deadLetterRoutingKey("RK_DEAD")
                //.ttl(10*1000) //该属性是队列的属性,设置消息的过期时间,消息在队列里面停留时间n毫秒后,就会把这个消息投递到死信交换机,针对的是所有的消息
                //.maxLength(20) //设置队列存放消息的最大个数,x-max-length属性值,当队列里面消息超过20,会把队列之前的消息依次放进死信队列
                .build();
    }

    //业务交换机
    @Bean
    public DirectExchange exchange() {
        return ExchangeBuilder.directExchange("Direct_E01").build();
    }

    //业务交换机与队列的绑定
    @Bean
    public Binding binding1(Queue queue1, DirectExchange exchange) {
        return BindingBuilder.bind(queue1).to(exchange).with("RK01");
    }

    //@RabbitListener(queues = "Direct_Q01")
//    public void receiveMessage(OrderingOk msg) {
//        log.info("消费者1 收到消息:"+ msg );
//        int  i= 5/0;
//    }

    @RabbitListener(queues = "Direct_Q01")
    public void receiveMessage(OrderingOk msg, Message message, Channel channel) throws IOException {

        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        System.out.println("消费者1 收到消息:" + msg + " tag:" + deliveryTag);

        channel.basicReject(deliveryTag, false);
//        try {
//            // 处理消息...
//            int  i= 5/0;
//            // 如果处理成功,手动发送ack确认 ,Yes
//            channel.basicAck(deliveryTag, false);
//        } catch (Exception e) {
//            // 处理失败,可以选择重试或拒绝消息(basicNack或basicReject)  NO
//            channel.basicNack(deliveryTag, false, false); // 并重新入队
//
//        }
    }
}

四、第二种场景:. 消费者发生异常,超过重试次数 。 其实spring框架调用的就是 basicNack

一般要和自动重启一起使用,否则死信队列收不到消息

#设置消费者自动应答模式
spring.rabbitmq.listener.simple.acknowledge-mode = auto
#开启自动应答重试机制
spring.rabbitmq.listener.simple.retry.enabled=true

package com.by.consumer;


import com.by.model.OrderingOk;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

@Configuration
@Slf4j
public class DeadConsumer {
    //死信交换机
    @Bean
    public DirectExchange deadExchange() {
        return ExchangeBuilder.directExchange("Dead_E01").build();
    }

    //死信队列
    @Bean
    public Queue deadQueue1() {
        return QueueBuilder.durable("Dead_Q01").build();
    }

    //死信交换机与死信队列的绑定
    @Bean
    public Binding deadBinding1(Queue deadQueue1, DirectExchange deadExchange) {
        return BindingBuilder.bind(deadQueue1).to(deadExchange).with("RK_DEAD");
    }

    //业务队列
    @Bean
    public Queue queue1() {
        return QueueBuilder
                .durable("Direct_Q01")
                .deadLetterExchange("Dead_E01")
                .deadLetterRoutingKey("RK_DEAD")
                //.ttl(10*1000) //该属性是队列的属性,设置消息的过期时间,消息在队列里面停留时间n毫秒后,就会把这个消息投递到死信交换机,针对的是所有的消息
                //.maxLength(20) //设置队列存放消息的最大个数,x-max-length属性值,当队列里面消息超过20,会把队列之前的消息依次放进死信队列
                .build();
    }

    //业务交换机
    @Bean
    public DirectExchange exchange() {
        return ExchangeBuilder.directExchange("Direct_E01").build();
    }

    //业务交换机与队列的绑定
    @Bean
    public Binding binding1(Queue queue1, DirectExchange exchange) {
        return BindingBuilder.bind(queue1).to(exchange).with("RK01");
    }

    //@RabbitListener(queues = "Direct_Q01")
//    public void receiveMessage(OrderingOk msg) {
//        log.info("消费者1 收到消息:"+ msg );
//        int  i= 5/0;
//    }

    @RabbitListener(queues = "Direct_Q01")
    public void receiveMessage(OrderingOk msg, Message message, Channel channel) throws IOException {

        long deliveryTag = message.getMessageProperties().getDeliveryTag();

        System.out.println("消费者1 收到消息:" + msg + " tag:" + deliveryTag);
        int a=10/0;
//        channel.basicReject(deliveryTag, false);
//        try {
//            // 处理消息...
//            int  i= 5/0;
//            // 如果处理成功,手动发送ack确认 ,Yes
//            channel.basicAck(deliveryTag, false);
//        } catch (Exception e) {
//            // 处理失败,可以选择重试或拒绝消息(basicNack或basicReject)  NO
//            channel.basicNack(deliveryTag, false, false); // 并重新入队
//
//        }
    }
}

五、第三种场景: 消息的Expiration 过期时长或队列TTL过期时间

    //业务队列
    @Bean
    public Queue queue1() {
        return QueueBuilder
                .durable("Direct_Q01")
                .deadLetterExchange("Dead_E01")
                .deadLetterRoutingKey("RK_DEAD")
                .ttl(10*1000) //该属性是队列的属性,设置消息的过期时间,消息在队列里面停留时间n毫秒后,就会把这个消息投递到死信交换机,针对的是所有的消息
                //.maxLength(20) //设置队列存放消息的最大个数,x-max-length属性值,当队列里面消息超过20,会把队列之前的消息依次放进死信队列
                .build();
    }

六、 第四种情景:  消息队列达到最大容量

    //业务队列
    @Bean
    public Queue queue1() {
        return QueueBuilder
                .durable("Direct_Q01")
                .deadLetterExchange("Dead_E01")
                .deadLetterRoutingKey("RK_DEAD")
//                .ttl(10*1000) //该属性是队列的属性,设置消息的过期时间,消息在队列里面停留时间n毫秒后,就会把这个消息投递到死信交换机,针对的是所有的消息
                .maxLength(5) //设置队列存放消息的最大个数,x-max-length属性值,当队列里面消息超过5,会把队列之前的消息依次放进死信队列
                .build();
    }
    /**
     * 测试直联交换机
     *
     * @throws IOException
     * @throws InterruptedException
     */
    @Test
    void contextLoads() throws IOException, InterruptedException {
        for (int i = 0; i < 8; i++) {
            OrderingOk orderingOk = OrderingOk.builder().id(1).name("张三"+i).build();
            directProvide.send(orderingOk);
        }
       
        System.in.read();
    }

id为1,2,3的被装进了死信队列,因为数据太老,业务队列优先要新的数据 

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

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

相关文章

neo4j使用详解(十一、cypher自定义函数语法——最全参考)

Neo4j系列导航&#xff1a; neo4j安装及简单实践 cypher语法基础 cypher插入语法 cypher插入语法 cypher查询语法 cypher通用语法 cypher函数语法 neo4j索引及调优 10.自定义函数 用户定义函数用Java编写&#xff0c;部署到数据库中&#xff0c;并以与任何其他Cypher函数相同的…

Java变量详解

​ 这里写目录标题 第一章、Java中的变量分类1.1&#xff09;变量分类1.2&#xff09;成员变量分类1.3&#xff09;成员变量和局部变量的区别 第二章、成员变量详解2.1&#xff09;成员变量作用域/权限修饰符2.2&#xff09;成员变量和成员属性的区别2.3&#xff09;成员变量初…

网络通信流程

建立完tcp请求再发起http请求 开启系统代理之后&#xff0c;以clash verge为例 127.0.0.1:7897&#xff0c;假设hci.baidu.com的IP为153.37.235.50 发起对hci.baidu.com的HTTP请求&#xff0c;由于开启了系统代理不进行DNS解析&#xff0c;浏览器调用socket()获得一个socket&a…

GlusterFS(GFS)分布式文件系统

一、GlusterFS的概述&#xff1a; GlusterFS 是一个开源的分布式文件系统。 只在扩展存储容器&#xff0c;提高性能 并且通过多个互联网络的存储节点的进行几余&#xff0c;以确保数据的可用性和一致性 由存储服务器、客户端以及NFS/Samba 存储网关&#xff08;可选&#xff0c…

软考中级之软件设计师---知识点汇总总结

软考中级之软件设计师---知识点汇总总结 软考介绍资格设置证书样本 计算机组成原理操作系统1. 进程的三态模型2. 磁盘调度算法 计算机网络1. 网络的分类2. 各层的互连设备3. 网络模型&#xff0c;协议簇4. 传输层协议TCP、UDP4.1 TCP (Transmission Control Protocol,传输控制协…

零代码与低代码开发平台

1、什么是低代码开发平台&#xff1f;什么是零代码开发平台&#xff1f; 零代码开发平台&#xff1a; 指的是不需要写代码就能够快速开发出业务应用/系统的平台。我们在工作中使用的业务应用&#xff0c;主要提供数据收集、数据处理、数据流转和展示等功能。零代码开发平台能够…

【超重磅牛市信号】减半倒计时12天!首波抛售潮接近尾声,大暴涨将如期而至!

3月&#xff0c;美国CPI环比出现小幅反弹由3.1%升至3.2%&#xff0c;美国制造业指数PMI反弹至50.3%呈现进入扩张期的态势&#xff0c;日本结束长达8年的负利率时代首次加息。这导致美国4月降息概率大幅下降&#xff0c;5月降息概率也跌至50%以下。 尽管如此&#xff0c;全球金融…

C#操作MySQL从入门到精通(8)——对查询数据进行高级过滤

前言 我们在查询数据库中数据的时候,有时候需要剔除一些我们不想要的数据,这时候就需要对数据进行过滤,比如学生信息中,我只需要年龄等于18的,同时又要家乡地址是安徽的,类似这种操作专栏第7篇的C#操作MySQL从入门到精通(7)——对查询数据进行简单过滤简单过滤方法就无法…

STL优先队列比较器

有两个比较器&#xff0c;在std里面&#xff0c;一个是greater&#xff0c;一个是less&#xff0c;他们都有一个可以指定的模板类型。 #include <bits/stdc.h> using namespace std; struct node {bool operator ()(const string& a, const string& b){return a…

蓝桥杯刷题-特殊年份

特殊年份 代码&#xff1a; def f(x)->bool:s list(x)if s[0]s[2] and int(s[1])1int(s[3]):return Trueelse:return False cnt 0 for _ in range(5):if f(input()):cnt1 print(cnt)

PC端音乐神器-解锁全网限制

打软件后就能发现&#xff0c;软件不需要我们登录&#xff0c;就可以使用,下载地址&#xff1a;PC端音乐神器.zip

什么是sso?

SSO&#xff08;Single Sign-On&#xff09;&#xff0c;即单点登录&#xff0c;是一种安全协议&#xff0c;它允许用户在多个应用程序之间使用同一组登录凭据进行身份验证。这意味着用户只需要登录一次&#xff0c;就可以访问多个需要身份验证的应用程序。 SSO的工作原理如下…

[C++][算法基础]合并集合(并查集)

一共有 n 个数&#xff0c;编号是 1∼n&#xff0c;最开始每个数各自在一个集合中。 现在要进行 m 个操作&#xff0c;操作共有两种&#xff1a; M a b&#xff0c;将编号为 a 和 b 的两个数所在的集合合并&#xff0c;如果两个数已经在同一个集合中&#xff0c;则忽略这个操…

【JavaEE】_Spring MVC项目获取Header

目录 1. 使用Servlet原生方法获取Header 2. 使用Spring注解获取Header 1. 使用Servlet原生方法获取Header .java文件内容如下&#xff1a; package com.example.demo.controller;import com.example.demo.Person; import org.springframework.web.bind.annotation.*; impor…

【C++进阶】用哈希实现unordered_set和unordered_map的模拟

&#x1fa90;&#x1fa90;&#x1fa90;欢迎来到程序员餐厅&#x1f4ab;&#x1f4ab;&#x1f4ab; 主厨&#xff1a;邪王真眼 主厨的主页&#xff1a;Chef‘s blog 所属专栏&#xff1a;c大冒险 总有光环在陨落&#xff0c;总有新星在闪烁 前言&#xff1a; 之前我…

网络安全 | 什么是区块链?

关注WX&#xff1a;CodingTechWork 概述 定义 区块链是一个共享的、不可篡改的账本&#xff0c;旨在促进业务网络中的交易记录和资产跟踪流程。资产可以是有形的&#xff08;如房屋、汽车、现金、土地&#xff09;&#xff0c;也可以是无形的&#xff08;如知识产权、专利、…

leetcode代码记录(最长连续递增序列

目录 1. 题目&#xff1a;2. 我的代码&#xff1a;小结&#xff1a; 1. 题目&#xff1a; 给定一个未经排序的整数数组&#xff0c;找到最长且 连续递增的子序列&#xff0c;并返回该序列的长度。 连续递增的子序列 可以由两个下标 l 和 r&#xff08;l < r&#xff09;确定…

极市平台 | 综述:一文详解50多种多模态图像融合方法

本文来源公众号“极市平台”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;综述&#xff1a;一文详解50多种多模态图像融合方法 0 极市导读 本工作总结了50篇论文中Lidar和camera的多模态融合的一些概念方法。笔者结合原文以及自…

变电站设计综合应用软件-光纤回路设计解决方案

产品概述 智能变电站光纤回路设计软件——让您的光纤设计之旅变得轻松而高效! 光纤回路设计作为智能变电站的关键环节,对电网的稳定运行起着至关重要的作用。为了让您的光纤设计之路更加顺畅,我们隆重推出了这款智能变电站光纤回路设计软件。这款软件以其简单易用的…

SpringBoot学习笔记-S2

1. SpringBoot中的常见注解 RequestBody&#xff1a;使SpringMVC框架可自动读取请求体里面的JSON格式的数据&#xff0c;转换成map类型的集合对象RestController&#xff1a;开发RESTful API 时使用&#xff0c;等价于ResponseBody Controller。RestController和Controller的…