RabbitMQ之延迟消息

news2024/9/25 11:09:47

文章目录

  • 前言
  • 一、死信交换机
  • 二、延迟消息
    • 死信交换机实现延迟消息
      • 图解流程
    • DelayExchange插件实现延迟消息
      • 安装插件
      • 声明延迟交换机
      • 发送延迟消息
  • 总结


前言

死信交换机、延迟消息


一、死信交换机

  • 当一个队列中的消息满足下列情况之一时,可以成为死信(dead letter):

    • 消费者使用basic.rejectbasic.nack声明消费失败,并且消息的requeue参数设置为false
    • 消息是一个过期消息,超时无人消费
    • 要投递的队列消息满了,无法投递
  • 如果一个队列中的消息已经成为死信,并且这个队列通过dead-letter-exchange属性指定了一个交换机,那么队列中的死信就会投递到这个交换机中,而这个交换机就称为死信交换机(Dead Letter Exchange)。而此时加入有队列与死信交换机绑定,则最终死信就会被投递到这个队列中。

  • 死信交换机有什么作用呢?

    • 收集那些因处理失败而被拒绝的消息
    • 收集那些因队列满了而被拒绝的消息
    • 收集因TTL(有效期)到期的消息

二、延迟消息

上面讲诉的两种作用可以用来实现消费者重试的处理,即将处理失败、溢出的消息放在特定队列由人工处理,与消费者重试时讲的RepublishMessageRecoverer作用类似(在RabbitMQ之消费者的可靠性里讲过RepublishMessageRecoverer):

  • 收集那些因处理失败而被拒绝的消息
  • 收集那些因队列满了而被拒绝的消息

收集因TTL(有效期)到期的消息这个作用可以用来实现延迟消息

死信交换机实现延迟消息

  • 声明一个Fanout交换机ttl.fanout、一个队列ttl.queue、一个Direct交换机dragon.direct、一个队列directt.queue。发送的消息设置有效期RoutingKey是blue。
  • ttl.queue通过dead-letter-exchange属性绑定dragon.direct交换机,使dragon.direct成为死信交换机,这样ttl.queue队列中过期的消息成为死信就会自动到达dragon.direct中。
  • direct.queue队列通过RoutingKey与死信交换机dragon.direct绑定,且RoutingKey为blue,这样,过期的消息先到达死信交换机,因死信交换机与direct.queue通过RoutingKey绑定,过期的消息通过RoutingKey由死信交换机路由到direct.queue队列。
  • 此时若有消费者消费direct.queue队列,就实现了延迟消费,具体的延时时间就是设置的有效期时间。

图解流程

在这里插入图片描述

注意:

  • RabbitMQ的消息过期是基于追溯方式来实现的,也就是说当一个消息的TTL到期以后不一定会被移除或投递到死信交换机,而是在消息恰好处于队首时才会被处理。
  • 当队列中消息堆积很多的时候,过期消息可能不会被按时处理,因此你设置的TTL时间不一定准确。

DelayExchange插件实现延迟消息

安装插件

插件下载地址

在这里插入图片描述

将下载的文件放到了/mnt目录下,然后输入sudo docker ps命令查看自己的rabbitmq是否正在运行,如果不在运行则输入sudo docker start id这里填你自己的容器id,如果不知道自己id的,输入sudo docker pa -a查看。

在这里插入图片描述

当容器运行起来后,输入sudo docker cp /mnt/rabbitmq_delayed_message_exchange-3.12.0.ez rabbit:/plugins命令,将刚插件拷贝到容器内plugins目录下。

在这里插入图片描述

拷贝完成后,输入sudo docker exec -it rabbit /bin/bash命令,进入容器。
进入plugins文件夹

在这里插入图片描述

在容器内plugins目录下,查看插件是否上传成功ls -l|grep delay

在这里插入图片描述

然后启动插件,在当前目录下输入rabbitmq-plugins enable rabbitmq_delayed_message_exchange命令

在这里插入图片描述

到这里插件安装就完成了,接下来我们需要重启RabbitMQ容器。执行exit命令退出RabbitMQ容器内部,然后执行docker restart 容器名命令重启RabbitMQ容器

声明延迟交换机

两种方式,自行选择
基于注解:

@RabbitListener(bindings = @QueueBinding(
        value = @Queue(name = "delay.queue", durable = "true"),
        exchange = @Exchange(name = "delay.direct", delayed = "true"),
        key = "delay"
))
public void listenDelayMessage(String msg){
    log.info("接收到delay.queue的延迟消息:{}", msg);
}

基于bean:

package com.itheima.consumer.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@Configuration
public class DelayExchangeConfig {

    @Bean
    public DirectExchange delayExchange(){
        return ExchangeBuilder
                .directExchange("delay.direct") // 指定交换机类型和名称
                .delayed() // 设置delay的属性为true
                .durable(true) // 持久化
                .build();
    }

    @Bean
    public Queue delayedQueue(){
        return new Queue("delay.queue");
    }
    
    @Bean
    public Binding delayQueueBinding(){
        return BindingBuilder.bind(delayedQueue()).to(delayExchange()).with("delay");
    }
}

发送延迟消息

@Test
void testPublisherDelayMessage() {
    // 1.创建消息
    String message = "hello, delayed message";
    // 2.发送消息,利用消息后置处理器添加消息头
    rabbitTemplate.convertAndSend("delay.direct", "delay", message, new MessagePostProcessor() {
        @Override
        public Message postProcessMessage(Message message) throws AmqpException {
            // 添加延迟消息属性
            message.getMessageProperties().setDelay(5000);
            return message;
        }
    });
}

注意:
延迟消息插件内部会维护一个本地数据库表,同时使用Elang Timers功能实现计时。如果消息的延迟时间设置较长,可能会导致堆积的延迟消息非常多,会带来较大的CPU开销,同时延迟消息的时间会存在误差。因此,不建议设置延迟时间过长的延迟消息。


总结

以上就是延迟消息的详细讲解了。

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

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

相关文章

微信小程序推送服务号消息(一)【Go+微信小程序+微信服务号+微信开放平台】

一、需求场景 业务需要给微信小程序用户在某些场景推送微信服务号消息,例如:订单即将超时,电子合同签约超时等; 二、开发准备 1、开通微信服务号 入口:微信公众平台 1.1 在服务号中获取推送消息所需的配置信息&#…

头插法巧解任意链表区间反转

题目链接:https://leetcode.cn/problems/reverse-linked-list-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150 头节点插入法,设置一个虚拟节点,不断循环到要反转的前面一个位置,哪怕是1也能包含进去。接着反…

Python UUID 完全指南

更多资料获取 📚 个人网站:ipengtao.com UUID(Universally Unique Identifier,通用唯一标识符)是一种全局唯一标识符生成方式,用于创建独一无二的标识符。Python的 uuid 模块提供了多种方法用于生成各种类…

四丶openlayer之瓦片地图

瓦片地图源于一种大地图解决方案,针对一整块非常大的地图进行切片,分成很多相同大小的小块地图,在用户访问的时候,再一块一块小地图加载,拼接在一起,从而还原成一整块大的地图。这样做的优点在于&#xff0…

【算法】FFT-1(递归实现)(不包括IFFT)

FFT 多项式多项式乘法复数及运算导数泰勒公式及展开式欧拉公式单位根 FFTCode IFFT 多项式 我们从课本中可以知道,一个 n − 1 n-1 n−1 次的多项式可以写成 a 0 a 1 x a 2 x 2 a 3 x 3 ⋯ a n − 1 x n − 1 a_{0}a_{1}xa_{2}x^2a_{3}x^3\dotsa_{n-1}x^{n-…

从 0 搭建 Vite 3 + Vue 3 Js版 前端工程化项目

之前分享过一篇vue3+ts+vite构建工程化项目的文章,针对小的开发团队追求开发速度,不想使用ts想继续使用js,所以就记录一下从0搭建一个vite+vue3+js的前端项目,做记录分享。 技术栈 Vite 3 - 构建工具 Vue 3 Vue Router - 官方路由管理器 Pinia - Vue Store你也可以选择vue…

2023年【G2电站锅炉司炉】考试试卷及G2电站锅炉司炉模拟试题

题库来源:安全生产模拟考试一点通公众号小程序 G2电站锅炉司炉考试试卷是安全生产模拟考试一点通生成的,G2电站锅炉司炉证模拟考试题库是根据G2电站锅炉司炉最新版教材汇编出G2电站锅炉司炉仿真模拟考试。2023年【G2电站锅炉司炉】考试试卷及G2电站锅炉…

Unity 接入TapADN播放广告时闪退 LZ4JavaSafeCompressor

通过跟踪安卓日志,发现报如下错误 Didnt find class "com.tapadn.lz4.LZ4JavaSafeCompressor" 解决方案: 去掉Minify这边的勾选,再打包即可。

香港优才计划是什么意思?一文详解2023年最新政策!

香港优才计划是什么意思?一文详解2023年最新政策! 目前香港优才计划申请火热,但是还是有很多新手不太了解这个项目,跟风申请绝对不是什么好事,先了解清楚再考虑也是对自己对家人的一种交代。这篇文章就再来科普下。 优…

AWVS 使用方法归纳

1.首先确认扫描的网站,以本地的dvwa为例 2.在awvs中添加目标 输入的地址可以是域名也可以是ip,只要本机可以在浏览器访问的域名或ip即可 添加地址及描述之后,点击保存,就会展现出目标设置选项 business criticality译为业务关键…

SpringCloud之服务网关Gateway组件使用——详解

目录 一、网关介绍 1.什么是服务网关 2. 为什么需要网关 3.网关组件在微服务中架构 二、服务网关组件 1. zuul 1.x 2.x(netflix 组件) 1.1 zuul版本说明 2. gateway (spring) 2.1 特性 2.2 开发网关动态路由 2.2.1.创建项目引入网关依赖 2.2.2 快捷方式配置路由 2.2…

C++学习——类和对象(上)

C学习——类和对象 一、面向对象和面向过程的初步认识二、什么是类 一、面向对象和面向过程的初步认识 我们之前学习了C语言,我们知道 ① C语言:C语言是一门面向过程的语言,关注的是过程,分析出求解问题的步骤,通过函…

Web安全之SQL注入:明明设置了强密码,为什么还会被别人登录?

一、背景 让我们先来看一个案例。某天,当你在查看应用的管理后台时,发现有很多异常的操作。接着,你很快反应过来了,这应该是黑客成功登录了管理员账户。于是,你立刻找到管理员,问他是不是设置了弱密码。管…

jenkins 代码执行 (CVE-2017-1000353)漏洞复现

jenkins 代码执行 (CVE-2017-1000353)漏洞复现 名称: jenkins 代码执行 (CVE-2017-1000353) 描述: ​Jenkins 可以通过其网页界面轻松设置和配置,其中包括即时错误检查和内置帮助。 插件 通过更新中心中的 1000 多个插件,Jenkins 集成了持续集成和持续…

分享一套MES源码,可以直接拿来搞钱的好项目

目前国内智能制造如火如荼,工厂信息化、数字化是大趋势。如果找到一个工厂,搞定一个老板,搞软件的朋友就能吃几年。 中国制造业发达,工厂林立,但是普遍效率不高,需要信息化提高效率。但是矛盾的地方在于&a…

删除链表的倒数第N个节点,剑指offerII(21),力扣

目录 题目地址: 题目: 相似类型题: 我们直接看本题题解吧: 解题方法: 难度分析: 解题分析: 解题思路(双指针): 代码实现: 代码说明: 代…

算法训练 第九周

一、移动零 1.双指针 我们可以设定两个指针i和j,其中i用来遍历整个数组,j用来遍历存放不为零的数的位置,当nums[i]不等于零时,就让nums[i]和nums[j]进行交换,然后j,当我们遍历完整个数组之后就完成了操作,…

基于Python的网络爬虫设计与实现

基于Python的网络爬虫设计与实现 摘要:从互联网时代开始,网络搜索引擎就变得越发重要。大数据时代,一般的网络搜索引擎不能满足用户的具体需求,人们更加注重特定信息的搜索效率,网络爬虫技术应运而生。本设计先对指定…

初识Linux(2).妈妈再也不用担心我Linux找不到门了。

文章目录 前言 1.man指令(重要):例如: 2.cp指令(重要):例如:把123.txt复制到a目录中类似window如下操作: 3.mv例如:类似window如下操作: 4.nano例…

Mysql快速查找用逗号分割的列中含有某个字符的行:FIND_IN_SET

看标题比较绕口,但是我举一个例子你就清楚了 这是一个查询:我现在想要的是attr_val中含有黑色属性的行: 你用模糊匹配可以,用REGEXP也行,下面介绍一种mysql自带的函数:FIND_IN_SET。它的用法是&#xff1a…