RabbitMQ死信交换机、TTL及延迟队列

news2024/11/25 1:02:07

一,死信交换机

1,什么是死信交换机

了解死信交换机之前我们先来了解一下什么是死信,当一个队列满足下面的三种情况的时候我们一般称为死信(dead letter):

  • 消费者使用basic.reject或 basic.nack声明消费失败,并且消息的requeue参数设置为false(当消费者未成功处理完消息的时候会给与其绑定的队列返回nack,此时就需要将消息重新入队requeue,如果将requeue参数设置成false消息就会变成死信了);
  • 消息已经过期了,过期的消息没有消费者进行消费就会变成死信;
  • 所需要投递的队列已经满了,最早的消息就会变成死信。

队列中的死信需要将消息转发给另一个交换机,此时整个交换机就被称为死信交换机,死信就可以往整个交换机里进行投递了;我们知道交换机不具备存储消息的能力,所以也需要一个死信队列与其进行绑定。

2,死信交换机投递的流程图

 

二,TTL

1,什么是TTL

TTL,也就是Time-To-Live。如果一个队列中的消息TTL结束仍未消费,则会变为死信,ttl超时分为两种情况:

  • 消息所在的队列设置了存活时间;
  • 消息本身设置了存活时间。

注意:这里是假定没有消费者绑定ttl队列,这样投递到ttl队列中的消息没有消费者进行消费,消息一定会超时,这样就可以将死信成功投递到死信交换机中了!

2,利用TTL模拟消息超时被投递到死信交换机中

1. 演示给队列设置超时时间的情况

1.1 在config包下定义TTLMessageConfig配置ttl交换机和ttl队列的信息,并将队列的超时时间设置为10s

@Configuration
public class TTLMessageConfig {

    @Bean
    public DirectExchange ttlDirectExchange(){
        return new DirectExchange("ttl.direct");
    }

    @Bean
    public Queue ttlQueue(){
        return QueueBuilder
                .durable("ttl.queue")
                .ttl(10000)//设置队列的超时时间是10s
                .deadLetterExchange("dl.direct")
                .deadLetterRoutingKey("dl")
                .build();
    }

    @Bean
    public Binding ttlBinding(){
        return BindingBuilder.bind(ttlQueue()).to(ttlDirectExchange()).with("ttl");
    }
}

1.2 利用注解的方式将ttl队列和死信交换机进行绑定并配置相关路由参数

@RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "dl.queue", durable = "true"),
            exchange = @Exchange(name = "dl.direct"),//默认交换机的类型为direct且为持久化的
            key = "dl"
    ))
    public void listenDlQueue(String msg) {
        log.info("消费者接收到了dl.queue的延迟消息" + msg);
    }

1.3 定义一个测试类进行消息发送观察消息发送成功和被处理的时间间隔是否是10s

@Test
    public void testTTLMessage() {
        // 1.准备消息
        Message message = MessageBuilder
                .withBody("hello, ttl messsage".getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .build();
        // 2.发送消息
        rabbitTemplate.convertAndSend("ttl.direct", "ttl", message);
        // 3.记录日志
        log.info("消息已经成功发送!");
    }

 2. 演示给消息设置超时时间的情况

给消息设置超时的场景只需要在消息发送的时候给消息设置上setExpiration参数即可:

@Test
    public void testTTLMessage() {
        // 1.准备消息
        Message message = MessageBuilder
                .withBody("hello, ttl messsage".getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .setExpiration("5000")//给消息设置超时时间
                .build();
        // 2.发送消息
        rabbitTemplate.convertAndSend("ttl.direct", "ttl", message);
        // 3.记录日志
        log.info("消息已经成功发送!");
    }

总结:

  • 给队列设置ttl属性,进入队列后超过ttl时间的消息变为死信;
  • 给消息设置ttl属性,队列接收到消息超过ttl时间后变为死信;
  • 两者共存时,以时间短的ttl为准。

三,延迟队列

1,什么是延迟队列

利用TTL结合死信交换机,我们实现了消息发出后,消费者延迟收到消息的效果。这种消息模式就称为延迟队列(Delay Queue)模式;在idea中可以使用延迟插件来对延迟队列进行操作(自行下载)。

2,延迟队列使用场景

延迟队列的使用场景包括:

  • 延迟发送短信 用户下单,如果用户在15 分钟内未支付,则自动取消;
  • 预约工作会议,20分钟后自动通知所有参会人员。

3,延迟队列的设计及使用

DelayExchange的本质还是官方的三种交换机,只是添加了延迟功能。因此使用时只需要声明一个交换机,交换机的类型可以是任意类型,然后设定delayed属性为true即可。

3.1 基于注解的方式声明一个延迟交换机

@RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "delay.queue", durable = "true"),
            exchange = @Exchange(name = "delay.direct", delayed = "true"),//添加delayed属性            
            表明是一个延迟交换机
            key = "delay"
    ))
    public void listenDelayExchange(String msg) {
        log.info("消费者接收到了delay.queue的延迟消息");
    }

3.2 向delay为true的交换机中发送消息,一定要给消息添加一个header:x-delay,值为延迟的时间,单位为毫秒

@Test
    public void testSendDelayMessage() throws InterruptedException {
        // 1.准备消息
        Message message = MessageBuilder
                .withBody("hello, ttl messsage".getBytes(StandardCharsets.UTF_8))
                .setDeliveryMode(MessageDeliveryMode.PERSISTENT)
                .setHeader("x-delay", 5000)//加上header属性
                .build();
        // 2.准备CorrelationData
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        // 3.发送消息
        rabbitTemplate.convertAndSend("delay.direct", "delay", message, correlationData);

        log.info("发送消息成功");
    }

延迟队列插件使用步骤:

声明一个交换机,添加delayed属性为true;

发送消息时,添加x-delay头,值为超时时间。

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

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

相关文章

深入 Linux 进程

问题 进程参数 和 环境变量 对于进程意味着什么? 进程参数和环境变量的意义 一般情况下,子进程的创建是为了解决某个子问题 子进程解决问题需要父进程的 "数据输入" (进程参数 & 环境变量) 设计原则: 子进程启动时必然用到…

SpringCloud学习路线(1)—— 从头开始的微服务

一、服务架构的历史 现有的服务框架: 单体架构 概念: 将业务所有功能集中在一个项目中开发,打包部署优点: 架构简单,部署成本低缺陷: 耦合度高 分布式架构 概念: 根据业务功能对系统进行拆分&a…

前端两种实现轮播图方式

今天研究两种简单实现轮播图功能的方式。 目录 Layui实现轮播图 码云下载 提取静态文件 示例 注意 参数说明 改为轮播图 增加图片资源文件 轮播栏目修改 改为上下切换 切换事件 脚本中绑定改变事件 控制器查看 Swiper实现轮播图 下载swiper 下载到本地 加载sw…

【数据结构】_3.List接口实现类ArrayList与线性表

目录 1.List接口 1.1 List接口的集合关系网络 1.2 List的使用 2. ArrayList与顺序表 2.1 线性表 2.2 顺序表 2.3 ArrayList 2.3.1 ArrayList的集合关系网络 2.3.2 ArrayList的使用 2.3.2.1 ArrayList的构造方法 2.3.2.2 ArrayList的扩容机制逻辑示图如下&#xff1…

企业如何通过CRM提高客户转化?

现如今,企业想要给潜在客户留下深刻的印象,那么就需要一系列的措施和手段。通过CRM管理系统让潜在客户信任企业,更好地进行客户培育,从而提高潜在客户转化。下面来说说,企业提高潜在客户转化的7个做法。 1、永远不要让…

input模糊搜索

input模糊搜索 getList() {let dicthis.queryParameters()let val this.queryParams["userName"]if (null ! val && ! val) {dic["userName"]*val*;}listPamsArchiveSearch(dic).then(response > {this.nameinfo response.data;});},主要问…

Spring Batch之读数据库——JdbcCursorItemReader之使用框架提供的BeanPropertyRowMapper(三十六)

一、BeanPropertyRowMapper介绍 参考我的另一篇博客: Spring Batch之读数据库——JdbcCursorItemReader(三十五)_人……杰的博客-CSDN博客 二、项目实例 1.项目框架 2.代码实现 BatchMain.java: package com.xj.demo27;import org.spri…

Echarts环形饼状图设置内外边框

上班快一个月了,最近再写echarts的项目,亚历山大啊 记录一下饼状图设置内外边框的代码 series: [{name: 项目分数,type: pie,radius: [50%, 70%],avoidLabelOverlap: false,labelLine: {show: true},data: [{value: 335, name: 970分以上},{value: 310…

python用playwright自动化测试程序打包exe

playwright自动化测试代码写好后,打包为exe运行在目标PC上可能出现错误。 原因: 1、运行的PC没有响应的浏览器。 2、playwright没有打包到代码中。 所以本例用AutoPytoExe为例来制作exe程序解决问题。 1、安装: 2、安装完成之后,…

CUDA并行归约算法(二)

CUDA并行归约算法&#xff08;二&#xff09; 文章目录 CUDA并行归约算法&#xff08;二&#xff09;前情回顾线程束分化内存组织Reference>>>>> 欢迎关注公众号【三戒纪元】 <<<<< 前情回顾 首先看下上节设计的核函数&#xff0c;如何进行并行…

基于FPGA的视频接口之HDMI1.4(以下)编码

简介 为什么要特别说明HDMI的版本,是因为HDMI的版本众多,代表的HDMI速度同样不同,当前版本在HDMI2.1速度达到48Gbps,可以传输4K及以上图像,但我们当前还停留在1080P@60部分,且使用的芯片和硬件结构有很大差别,故将HDMI分为两个部分说明1080@60以下分辨率和4K以上分辨率(…

docker运行redis容器

参考文章 Redis从入门到精通&#xff08;4&#xff09;&#xff1a;docker运行redis容器详解 问题及总结 docker 命令 拉取镜像&#xff1a;docker pull redis 或者 docker pull redis:bullseye&#xff1b;查看镜像&#xff1a;docker image ls&#xff1b;直接运行 redis…

Flask SQLAlchemy_Serializer ORM模型序列化

在前后端分离项目中&#xff0c;经常需要把ORM模型转化为字典&#xff0c;再将字典转化为JSON格式的字符串。在遇到sqlalchemy_serializer之前&#xff0c;我都是通过类似Java中的反射原理&#xff0c;获取当前ORM模型的所有字段&#xff0c;然后写一个to_dict方法来将字段以及…

Golang假共享(false sharing)详解

多核处理器(SMP)系统中, 每一个处理器都有一个本地高速缓存。内存系统必须保证高速缓存的一致性。当不同处理器上的线程修改驻留再同一高速缓存中的变量时就会发生假共享(false sharing),结果导致高速缓存无效,并强制更新,进而影响系统性能。 什么是假共享(false sharin…

论文解读|VoxelNet:基于点云的3D物体检测的端到端学习

原创 | 文 BFT机器人 01 摘要 论文提出了表述了一个新的基于点云的3D检测方法&#xff0c;名为VoxelNet&#xff0c;该方法是一个端到端可训练的深度学习架构&#xff0c;利用了稀疏点云的结构特性&#xff0c;直接在稀疏的3D点上进行操作&#xff0c;并通过高效的并行处理体素…

Stable Diffusion - ChatGPT4 与 Stable Diffusion 结合提供无限创意构图

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/131782672 ChatGPT 和 StableDiffusion 结合使用的优势&#xff1a; 高效率&#xff1a;ChatGPT 可以在很短的时间内完成复杂的语言任务&#xf…

Kotlin基础(六) 枚举类和扩展

前言 本文主要讲解kotlin枚举类和扩展 Kotlin文章列表 Kotlin文章列表: 点击此处跳转查看 目录 1.1 枚举类 1.1.1 枚举类的基本用法 Kotlin中的枚举类&#xff08;enum class&#xff09;用于定义一组具有预定义值的常量。它们在许多情况下都很有用&#xff0c;例如表示一组…

介绍性能压力测试的重要性

在当今数字化时代&#xff0c;软件和应用程序的性能对于用户体验和业务成功至关重要。为了确保系统在面临高负载和压力时能够正常运行&#xff0c;性能压力测试成为一项不可或缺的活动。本文将介绍性能压力测试的重要性。 性能压力测试是一种通过模拟实际场景中的负荷和用户访问…

Echarts中饼状图,图例显示value而不是name

直接上代码 formatter(name) {var tarValue;for (var i 0; i < data.length; i) {if (data[i].name name) {tarValue data[i].value;}}var v tarValue;return [tarValue]} 效果图

spring boot 多模块项目搭建Knife4j文档,swagger-ui x2

介绍: knife4j jeecg-boot用的就是这个&#xff0c;我之前要搭过swagger-ui&#xff0c;但外观&#xff0c;体验都没有knife4j好&#xff0c;我没记错的话已经停止发布版本了&#xff0c;所以我的多模块项目就用到了这个&#xff0c;还搭建了jwt token获取我也是在网上找的…