RabiitMQ延迟队列(死信交换机)

Dead Letter Exchange(死信交换机)

        在MQ中,当消息成为死信(Dead message 死掉的信息)后,消息中间件可以将其从当前队列发送到另一个队列中,这个队列就是死信队列。而 在RabbitMQ中,由于有交换机的概念,实际是将死信发送给了死信交换机(Dead Letter Exchange,简称DLX)。死信交换机和死信队列和普通的没有区别。

消息成为死信的情况

  1. 队列消息长度到达限制
  2. 消费者拒签消息,并且不把消息重新放入原队列
  3. 消息到达存活时间未被消费

有些队列的消息成为死信后,(比如过期了或者队列满了)这些死信一般情况下是会被 RabbitMQ 清理的。但是你可以配置某个交换机为此队列的死信交换机,该队列的消息成为死信后会被重新发送到此 DLX 。至于怎么处理这个DLX中的死信就是看具体的业务场景了,DLX 中的信息可以被路由到新的队列。

  • 生产者 

    /**
     * 普通交换机绑定普通交换机
     *
     * @return
     */
    @Bean
    public Queue queueA() {
        //信息配置
        Map<String, Object> map = new HashMap<>();
        //message在该队列queue的存活时间最大为15秒
        map.put("x-message-ttl", 15000);
        //x-dead-letter-exchange参数是设置该队列的死信交换器(DLX)
        map.put("x-dead-letter-exchange", "exchangeB");
        //x-dead-letter-routing-key参数是给这个DLX指定路由键
        map.put("x-dead-letter-routing-key", "queueB");
        return new Queue("queueA", true, false, false, map);
    }

    @Bean
    public DirectExchange exchangeA() {
        return new DirectExchange("exchangeA");
    }

    @Bean
    public Binding bindingA() {
        return BindingBuilder
                .bind(queueA())
                .to(exchangeA()).with("queueA");
    }

    /**
     * 死信交换机绑定死信交换机
     *
     * @return
     */
    @Bean
    public Queue queueB() {
        return new Queue("queueB");
    }

    @Bean
    public DirectExchange exchangeB() {
        return new DirectExchange("exchangeB");
    }

    @Bean
    public Binding bindingB() {
        return BindingBuilder
                .bind(queueB())
                .to(exchangeB()).with("queueB");
    }
  •  模拟发送请求
    @RequestMapping("/send6")
    public String sendSix() throws JsonProcessingException {
        rabbitTemplate.convertAndSend("exchangeA", "queueA", "检查订单是否过期");
        return "🫶";
    }

这时我发送请求到队列queueA,并设置了15秒的延迟,将超时的信息调用到死信交换机中。在这里我是没开启消费者所有没有消费者去处理该请求的,信息在queueA队列等待15秒后将会转到死信交换机queueB队列进行处理:

延迟队列

  • 延迟队列,即消息进入队列后不会立即被消费,只有到达指定时间后,才会被消费。经典的应用场景是下单减库存。 

        根据以上结论,在rabbitmq中消费者只要接到信息就会自动确认进行处理。所以在上面并没有开启消费者,当请求時效后(如订单未支付,定时30分钟自动取消功能)我们不应该再让它正常处理,而把该请求放到死信交换机中安排对应的处理,所以我们需要打消费者自动处理请求改成手动。 

  • 如果手动确认则当消费者调用 ack、nack、reject 几种方法进行确认,手动确认可以在业务失败后进行一些操作,如果消息未被 ACK 则会发送到下一个消费者

  • 如果某个服务忘记 ACK 了,则 RabbitMQ 不会再发送数据给它,因为 RabbitMQ 认为该服务的处理能力有限

  • ACK 机制还可以起到限流作用,比如在接收到某条消息时休眠几秒钟

  • 消息确认模式有:

  1. AcknowledgeMode.NONE:自动确认
  2. AcknowledgeMode.AUTO:根据情况确认
  3. AcknowledgeMode.MANUAL:手动确认

确认消息(局部方法处理消息)

  • 默认情况下消息消费者是自动 ack (确认)消息的,如果要手动 ack(确认)则需要修改确认模式为 manual

消费者添加手动确认消息配置配置 :

spring:
  rabbitmq:
    listener:
      simple:
        acknowledge-mode: manua
  • 消费者接受消息: 
package com.ycxw.consumer.demos;

import com.rabbitmq.client.Channel;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * @author 云村小威
 * @create 2024-01-25 15:36
 */
@Component
public class DLXReceiver {

    @RabbitListener(queues = {"queueA"})
    @RabbitHandler
    public void handlerA(String msg, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws IOException {
        System.out.println("已接受到队列queueA传递过来的消息:" + msg);
        channel.basicReject(tag, false);// 拒接消息,如果为true则拒绝后又从新回到队列被接受(循环),除非消息过期。
        //channel.basicAck(tag, true); 确认消息()一次性全接受,如果为false则接受一次
    }

    /**
     * 接受死信消息
     *
     * @param msg
     */
    @RabbitListener(queues = {"queueB"})
    @RabbitHandler
    public void handlerB(String msg) {
        /**
         * ...接受到信息,去数据库处理
         */
        System.out.println("已接受到队列queueB传递过来的消息:" + msg);
    }
}

 第一次进入普通队列别拒绝后,转到死信队列中处理...

需要注意的 basicAck 方法需要传递两个参数

  • deliveryTag(唯一标识 ID):当一个消费者向 RabbitMQ 注册后,会建立起一个 Channel ,RabbitMQ 会用 basic.deliver 方法向消费者推送消息,这个方法携带了一个 delivery tag, 它代表了 RabbitMQ 向该 Channel 投递的这条消息的唯一标识 ID,是一个单调递增的正整数,delivery tag 的范围仅限于 Channel

  • multiple:为了减少网络流量,手动确认可以被批处理,当该参数为 true 时,则可以一次性确认 delivery_tag 小于等于传入值的所有消息

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

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

相关文章

Android14音频进阶:MediaPlayerService如何启动AudioTrack 上篇(五十五)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒体系统工程师系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只…

正确入市时机3秒抓住,WeTrade众汇无偿实例分享

在上篇文章中&#xff0c;WeTrade众汇无偿分享如何3秒抓住正确入市的时机&#xff0c;今天让我们通过一个例子来验证这个策略的正确性。 对于突破策略&#xff0c;WeTrade众汇用了同样的图表来演示挤压交易。蓝色箭头表示变窄的区域&#xff0c;红色箭头表示烛台穿过下层。当它…

成功解决RuntimeError: batch2 must be a 3D tensor

成功解决RuntimeError: batch2 must be a 3D tensor。 &#x1f335;文章目录&#x1f335; &#x1f333;引言&#x1f333;&#x1f333;问题初探&#xff1a;为什么会出现这个错误&#xff1f;&#x1f333;&#x1f333;解决方案&#xff1a;如何避免和修复这个错误&#x…

啤酒:探索精酿啤酒与川菜的麻辣味觉之旅

在中国的饮食文化中&#xff0c;川菜以其麻辣味道而闻名于世。当Fendi Club啤酒遇上川菜&#xff0c;会碰撞出怎样的味觉火花&#xff1f;今天&#xff0c;让我们一起踏上这场探索Fendi Club啤酒与川菜麻辣味觉之旅。 首先&#xff0c;让我们来了解一下Fendi Club啤酒。这款啤酒…

mfc110.dll是什么?解决mfc110.dll丢失windows系统常见问题

今天我在打开电脑软件时候&#xff0c;突然报错出现找不到mfc110.dll丢失&#xff0c;无法打开软件&#xff0c;我不知道是什么原因&#xff0c;后面找了很久才找到解决方法&#xff0c;那么mfc110.dll是什么&#xff1f;为什么会丢失和mfc110.dll解决方法是什么&#xff0c;今…

年货大数据(年货节数据/电商行业数据):龙年再添两个黑马食品饮料品类,增长11倍!

年货零食三大件&#xff1a;牛奶、糖果和炒货。今年再多两大件&#xff0c;礼品卡券和腊味。 根据鲸参谋数据显示&#xff0c;今年坚果炒货、糖果、牛奶乳品、饮料等品类依然是长期的年货热门品类。1月前三周&#xff0c;牛奶乳品销量环比增长68%&#xff0c;销售额环比增长55…

ThreadLocal及阿里(TransmittableThreadLocal,TTL)分析

TTL类关系图 ThreadLocal <- InheritableThreadLocal <- TransmittableThreadLocal 1. ThreadLocal ThreadLocal 类提供线程本地&#xff08;局部&#xff09;变量。每个线程都有自己独立初始化的变量副本。 TheadLocal 允许我们存储仅由特定线程访问的数据&#xff0c;…

C#在既有数组中插入另一个数组:Array.Copy方法 vs 自定义插入方法

目录 一、使用的方法 1.使用Array.Copy方法 2.Copy(Array, Int32, Array, Int32, Int32) 3. 使用自定义的方法 二、实例 1.示例1&#xff1a;使用Array.Copy方法 2.示例2&#xff1a;使用自定义的方法 一、使用的方法 1.使用Array.Copy方法 首先定义了一个名为InsertAr…

可解释性AI(XAI):开启AI决策过程透明化,重塑信任与解决伦理偏见

文章目录 每日一句正能量前言可解释性AI的定义与重要性什么是可解释性&#xff1f;促进技术应用的可信度提高技术的透明度保护隐私和数据权益促进AI的社会接受度 可解释性AI的挑战与难点可解释性AI的应用场景后记 每日一句正能量 宁可因高目标而脖子硬&#xff0c;也不要为低目…

Java+SpringBoot:构建稳定高效的计算机基础教学平台

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

《Java程序设计》实验报告(四)之数据库操作

实验内容及步骤&#xff1a; 数据库的建立、删除等。&#xff08;1&#xff09;代码&#xff1a; package liyuxuan.study.java; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class CreateD…

npm 上传一个自己的应用(5) 删除自己发送到NPM官网的指定工具版本

上文 npm 上传一个自己的应用(4) 更新自己上传到NPM中的工具版本 并就行内容修改 我们更新了项目内容 然后更新了项目版本 那么 一些已经过时 甚至 当时上传的东西就有问题 我们又该怎么删除版本呢&#xff1f; 首先 我们还是要先登录 npm npm login然后 根据要求填写 Userna…

迅为RK3588开发板windows与开发板互传使用U盘进行拷贝

1 将 U 盘(U 盘的格式必须为 FAT32 格式&#xff0c;大小在 32G 以下)插到开发板的 usb 接口&#xff0c;串口打印信息如下所示&#xff0c;U 盘的设备节点是/dev/sdb4。U 盘的设备节点不是固定的&#xff0c;根据实际情况来查看设备节点。 2 输入以下命令挂载 U 盘&#xff0c…

新版本nginx安装提示需要openssl的问题

新版本的nginx安装的时候未发现openssl的路径&#xff0c;有两种方式解决 方式一&#xff1a; 找到本地nginx的解压目录中 &#xff0c;例如我的放到root下面了。 进入 /root/nginx1.24.0/auto/lib/openssl/conf 目录下修改内容 &#xff0c;这两行都需要修改&#xff0c;…

华为配置访客接入WLAN网络示例(MAC优先的Portal认证)

配置访客接入WLAN网络示例&#xff08;MAC优先的Portal认证&#xff09; 组网图形 图1 配置WLAN MAC优先的Portal认证示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 某企业为了提高WLAN网络的安全性&#xff0c;采用MAC优先的外置Portal认…

【51单片机】外部中断和定时器中断

目录 中断系统中断介绍中断概念 中断结构及相关寄存器中断结构中断相关寄存器 外部中断实验外部中断配置软件设计实验现象 定时器中断定时器介绍51 单片机定时器原理51 单片机定时/计数器结构51 单片机定时/计数器的工作方式 定时器配置硬件设计软件设计实验现象 中断系统 本章…

10个优化Instagram SEO的必学策略

Instagram SEO 是优化 Instagram 内容以使其在平台搜索结果中被发现的做法。如果你希望你可以更快的让你的Ins获得流量&#xff0c;做好SEO就成功了一半。Instagram 搜索结果包括相关内容、帐户、音频、主题标签和地点&#xff0c;下面为你总结10个策略技巧&#xff01; 一、In…

三网码支付系统源码,三网免挂有PC软件,有云端源码,附带系统搭建教程

搭建教程 1.先上传云端源码 然后配置Core/Config.php文件里面数据库信息注改&#xff1b;数据库帐号密码 2.云端源码里面Core/Api_Class/Instant_Url_List.php文件配置终端地址注改&#xff1b;第4 http://终端地址/ 3.导入云端数据库 账号admin 密码123456注改&#xff1…

使用python揭秘CSDN热门付费专栏惊人真相

文章目录 1.csdn付费专栏词云2.浏览器抓包分析3.API接口测试4.需要使用的python库5.爬虫与数据分析设计6. 完整代码7.最终的成果8.惊人真相在这里 1.csdn付费专栏词云 我们如何分析csdn热门付费专栏呢&#xff1f; 热门专栏是动态的&#xff0c;所以我们爬取的数据是一直变化的…

5-4、S加减单片机程序【51单片机+L298N步进电机系列教程】

↑↑↑点击上方【目录】&#xff0c;查看本系列全部文章 摘要&#xff1a;本节介绍实现步进电机S曲线运动的代码 一、目标功能 实现步进电机转动总角度720&#xff0c;其中加减速各90 加速段&#xff1a;加速类型&#xff1a;S曲线  加速角度&#xff1a;角度为90  起步速度…