RabbitMQ(一)使用死信队列实现延迟队列消费

【RabbitMQ笔记(六)】之消费端限流,TTL,死信队列,延迟队列 一. 消费端限流 (一)概述         RabbitMQ能够削峰平谷,保障系统流量的稳定,但是若在消费端没有限制,那么消费端会有崩掉的风险,因此,我们要给消费端限流,限制每次消费端能够从Rabbitmq获取的消息数量。 (二)消费端限流机制         1. 设置Ack机制为手动确认,因为只有手动确认,我们才能够通过限制是否返回确认来限制消费端的流量。在监听类容器中设置属性acknowledge=”man 阅读详情

在使用rabbitmq实现延迟消费时,需要先明白什么是死信队列,什么是延迟队列。
rabbitmq并没有直接支持延迟队列,延迟队列是通过死信队列来实现的。

死信队列

DLX(Dead Letter Exchange),死信交换器。当队列中的消息被拒绝、或者过期会变成死信,死信可以被重新发布到另一个交换器,这个交换器就是DLX,与DLX绑定的队列称为死信队列。
造成死信的原因:

信息被拒绝
信息超时
超过了队列的最大长度

延迟队列

延迟队列存储的是延迟消息,延迟消息指的是,当消息被发发布出去之后,并不立即投递给消费者,而是在指定时间之后投递。如:在订单系统中,订单有30秒的付款时间,在订单超时之后在投递给消费者处理超时订单。
rabbitMq没有直接支持延迟队列,可以通过死信队列实现。在死信队列中,可以为普通交换器绑定多个消息队列,假设绑定过期时间为5分钟,10分钟和30分钟,3个消息队列,然后为每个消息队列设置DLX,为每个DLX关联一个死信队列。当消息过期之后,被转存到对应的死信队列中,然后投递给指定的消费者消费。

整体项目结构图

在这里插入图片描述

父pom文件

<!-- 定义公共资源版本 -->
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.5.RELEASE</version>
        <relativePath />
    </parent>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-parent</artifactId>
                <version>2.0.5.RELEASE</version>
            </dependency>
        </dependencies>
    </dependencyManagement>

死信队列生产者

pom文件

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

application.yml文件

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: admin
    password: admin
    #发布者确认
    publisher-confirms: true

server:
  port: 9041

rabbitmq:
  #死信队列(最终消费者会消费此队列)
  dlx:
    exchange: mayikt_order_dlx_exchange
    queue: mayikt_order_dlx_queue
    routingKey: dlx
  driver:
    exchange: exchange
    routingKey: routingkey
    queue: queue

rabbitmq配置

@Configuration
public class RabbitmqConfiguration {

    /**
     * exchange交换器名字
     */
    @Value("${rabbitmq.driver.exchange}")
    private String driverUpExchangeName;
    /**
     * 路由键名字
     */
    @Value("${rabbitmq.driver.routingkey}")
    private String driverUpRoutingKey;
    /**
     * queue
     */
    @Value("${rabbitmq.driver.queue}")
    private String driverUpQueue;
    /**
     * 死信交换机
     */
    @Value("${rabbitmq.dlx.exchange}")
    private String dlxExchange;
    /**
     * 死信队列
     */
    @Value("${rabbitmq.dlx.queue}")
    private String dlxQueue;
    /**
     * 死信路由
     */
    @Value("${rabbitmq.dlx.routingKey}")
    private String dlxRoutingKey;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @PostConstruct
    public void initRabbitTemplate() {
        // 设置生产者消息确认
        rabbitTemplate.setConfirmCallback(new RabbitConfirmCallback());
    }


    //死信交换机
    @Bean
    public DirectExchange dlxExchange() {
        return new DirectExchange(dlxExchange);
    }


    //声明死信队列 (真正的队列)

    @Bean
    public Queue dlxQueue() {
        return new Queue(dlxQueue);
    }

    /**
     * 声明订单业务交换机(基本交换机)
     */
    @Bean
    public DirectExchange orderExchange() {
        return new DirectExchange(driverUpExchangeName);
    }

    /**
     * 声明订单队列(用于基本交换机和基本路由到死信队列的绑定)
     */
    @Bean
    public Queue orderQueue() {
        Map<String, Object> arguments = new HashMap<>(2);
        // 绑定我们的死信交换机
        arguments.put("x-dead-letter-exchange", dlxExchange);
        // 绑定我们的路由key
        arguments.put("x-dead-letter-routing-key", dlxRoutingKey);
        return new Queue(driverUpQueue, true, false, false, arguments);
    }

    /**
     * (创建基本交换机+基本路由 -> 死信队列 的绑定)
     */
    @Bean
    public Binding orderBinding() {
        return BindingBuilder.bind(orderQueue()).to(orderExchange()).with(driverUpRoutingKey);
    }

    /**
     * (死信交换机+死信路由->真正队列 的绑定)
     */
    @Bean
    public Binding binding() {
        return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with(dlxRoutingKey);
    }
}

生产者消息确认

@Slf4j
public class RabbitConfirmCallback implements RabbitTemplate.ConfirmCallback {

	@Override
	public void confirm(CorrelationData correlationData, boolean ack, String cause) {
		log.info("(start)生产者消息确认=========================");
		log.info("correlationData:[{}]", correlationData);
		log.info("ack:[{}]", ack);
		log.info("cause:[{}]", cause);
		if (!ack) {
			log.info("消息可能未到达rabbitmq服务器");
		}
		log.info("(end)生产者消息确认=========================");
	}
}

controller

@RestController
@RequestMapping("/rabbitmq")
public class SendController {

    @Autowired
    private DriverRabbitmqServce driverRabbitmqServce;

    @PostMapping("/send")
    public void send() {
        driverRabbitmqServce.sendDriverMessage(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + " 发送了死信消息");
    }

}

service

@Slf4j
@Service
public class DriverRabbitmqServce {

    /**
     * exchange交换器名字
     */
    @Value("${rabbitmq.driver.exchange}")
    private String driverUpExchangeName;
    /**
     * 路由键名字
     */
    @Value("${rabbitmq.driver.routingkey}")
    private String driverUpRoutingKey;

    @Autowired
    private AmqpTemplate amqpTemplate;

    //处理待发送消息()
    private MessagePostProcessor messagePostProcessor() {
        return new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                //设置有效期 毫秒单位 后过期
                message.getMessageProperties().setExpiration("10000");
                return message;
            }
        };
    }

    public void sendDriverMessage(String driverNumber) {
        //向消息队列发送消息
        //参数一 : 交换器   参数三 : 消息
        this.amqpTemplate.convertAndSend(driverUpExchangeName, driverUpRoutingKey, driverNumber, messagePostProcessor());
        log.info("向消息队列发送消息 {}", driverNumber);
    }
}

项目结构如图
在这里插入图片描述

死信队列消费者

pom文件

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

application.yml

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: admin
    password: admin
    listener:
      simple:
        #设置消费端手动 ack   none不确认  auto自动确认  manual手动确认
        acknowledge-mode: manual
        retry:
          #开启消费者重试机制(为false时关闭消费者重试(开启消息重新投递),这时消费端代码异常会一直重复收到消息)
          enabled: true
          #重试次数5(重新投递次数)
          max-attempts: 5
          #重试时间间隔
          initial-interval: 5000
        #重试次数超过上面的设置之后是否丢弃(消费者listener抛出异常,是否重回队列,默认true:重回队列, false为不重回队列(结合死信交换机)
#        default-requeue-rejected: true
        #消费之最大数量
        max-concurrency: 1

server:
  port: 9040

rabbitmq:
  dlx:
    name: mayikt_order_dlx_name
    exchange: mayikt_order_dlx_exchange
    queue: mayikt_order_dlx_queue
    routingKey: dlx

消费者

@Slf4j
@Component
@RabbitListener(
        //绑定队列
        bindings = @QueueBinding(
                //需要指定queue的名字
                value = @Queue(
                        //配置队列名称
                        value = "${rabbitmq.dlx.name}",
                        //是否是一个可删除的临时队列 --> 消息持久化
                        autoDelete = "false"
                ),
                //配置交换器
                exchange = @Exchange(
                        //指定交换器名称
                        value = "${rabbitmq.dlx.exchange}",
                        //指定具体的交换器类型,有常量类指定
                        type = ExchangeTypes.DIRECT
                ),
                //路由键
                key = "${rabbitmq.dlx.routingkey}"
        )
)
public class DriverListen {


    /**
     * 接受消息的方法,采用消息队列监听机制
     */
    @RabbitHandler
    public void pay(String msg, Message message, Channel channel) throws Exception {
        log.info("consumers 接受到了 rabbitmq 消息 {}", msg);
        //消费者手动ack机制
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        /**
         * 下面代码测试异常重试机制
         */
//        try {
//            int i = 1 / 0;
//        } catch (Exception e) {
//            //如果不抛出异常,catch之后无法重试
//            throw new RuntimeException("我异常了");
//        }
    }
}

项目结构图
在这里插入图片描述

只需要修改配置文件即可使用,相关位置都标明了注解,易于上手

项目测试,启动消费者和生产者,调用生产者的controller接口即可。查看消费者的消费时间。

关注公众号
在这里插入图片描述

每周会更新干货知识

ActiveMQ、RabbitMQ、Kafka、RocketMQ在优先级队列、延迟队列、死信队列、重试队列、消费模式、广播模式的区别 ActiveMQ、RabbitMQ、Kafka、RocketMQ这四款消息队列在优先级队列、延迟队列、死信队列、重试队列、消费模式、广播模式等方面各有其特点和差异。 阅读详情

相关推荐

RabbitMQ高级特性(消息的可靠投递、Consumer Ack、消费端限流、TTL、死信队列、延迟队列、日志与监控、消息追踪)

一、 消息的可靠投递 可以通过 confirm 确认模式,return 返回模式,确定消息的可靠性投递 * confirm 确认模式 消息从producer到exchange,则会返回一个confirmCallback. * return 返回模式 消息从exchange到queue投递失败,则会返回一个returnCallback 1、准备工作 (1)创建rabbitmq-producer-sp...

Java_c# 677

RabbitMQ实现延迟队列

RabbitMQ 延迟队列是指将消息先放入队列中,但是并不立即消费该消息,而是在一定时间后再进行消费的队列。延迟队列可以用来解决某些需要经过一段时间才能处理的任务,例如超时未支付订单的关闭、定时发送消息等场景。

weixin_58724261的博客 2361

RabbitMQ高级特性2 、TTL、死信队列和延迟队列

1. 死信交换机和死信队列和普通的没有区别2. 当消息成为死信后,如果该队列绑定了死信交换机,则消息会被死信交换机重新路由到死信队列3. 消息成为死信的三种情况:1. 队列消息长度到达限制;2. 消费者拒接消费消息,并且不重回队列;3. 原队列存在消息过期设置,消息到达超时时间未被消费;

wql56789的博客 1655

RabbitMQ 如何使用延迟队列

假设我们正在设计一个线上售卖电影票的系统,用户购票后有 15 分钟时间进行付款,如果用户在 15 分钟内未付款,订单将自动取消并释放电影票库存。这里,我们可以利用 RabbitMQ 的延迟队列机制,在用户购票时发送一条延迟消息到 RabbitMQ,并设定延迟时间为 15 分钟。如果用户未在 15 分钟内完成付款,延迟消息将被消费者接收并处理订单取消的逻辑。,可以基于消息属性设置延迟时间,在设定的延迟时间后,将消息发送到目标队列。类型的交换机,并设定延迟队列,用于处理延迟消息。

NeedForSpeed 1101

英特尔SVS:十亿级向量搜索的硬件优化与LVQ压缩实战

向量搜索作为处理高维嵌入数据的核心技术,其核心原理是通过近似最近邻(ANN)算法在海量数据中快速找到相似项,以解决传统暴力搜索在规模上的瓶颈。这项技术的核心价值在于为推荐系统、图像检索、自然语言处理等AI应用提供高效的相似性匹配能力,尤其在RAG架构中成为连接非结构化数据与大语言模型的关键基础设施。面对十亿级数据带来的内存与算力挑战,局部自适应向量量化(LVQ)等压缩技术通过减少存储开销并保持精度,而硬件层面的深度优化则利用AVX-512等指令集大幅提升计算效率。本文聚焦于英特尔开源的Scalable Ve

weixin_42526310的博客 551

Ceres-solver examples之pose_graph_3d学习笔记

Ceres-solver examples之pose_graph_3d学习笔记简要说明变量说明关键步骤一、Costfunction的搭建其中包括:二、构造Problem 简要说明 ceres-solver库是google的非线性优化库,可以对slam问题,机器人位姿进行优化,使其建图的效果得到改善。pose_graph_3d是官方给出的二维平面上机器人位姿优化问题,需要读取一个g2o文件,运行程序...

幽冥小龙的博客 3888

RabbitMQ--延迟队列--使用/原理

本文介绍RabbitMQ的延迟队列的用法。 本内容也是Java后端面试中常见的问题。

IT利刃出鞘的博客 3361

OpenCV图像去畸变实战指南:从原理到参数调优(附完整代码与效果对比)

本文深入解析了OpenCV图像去畸变的原理与实战技巧,详细对比了标准透视、鱼眼及全能型omnidir三种校正函数的核心参数调优方法。通过分析alpha、balance、centerX/Y及focalScale四大参数对输出效果的影响,并结合完整代码与效果对比图,帮助开发者精准校正镜头畸变,提升计算机视觉任务精度。

weixin_29046611的博客 341

业务日记——延时队列/延时消费

一、基本定义 延时/定时消息是指生产者(producer)发送消息到server后,server并不将消息立即发送给消费者(consumer),而是在producer指定的时间之后送达。 二、常用的使用场景 任务超时处理。例如 订单系统中,如果某个用户在 30分钟内没有支付,则订单自动进行过期处理 任务延时处理。例如订餐系统中,下单成功60s之后 给用户发短信通知 定时任务。例如现在通过手机...

Luffyu的博客 1376

windows10 + wsl2安装docker

一、安装wsl https://docs.microsoft.com/zh-cn/windows/wsl/install-win10 1.1以管理员身份运行powershell 1.2执行如下命令 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 1.3重启电脑 1.4 重启电脑后,如果需要安装wsl2, 则安装官方文档继续后续操作,因我...

happytree001的博客 1567

virtuoso如何导出def?

在DEF Out界面,填写def name,library name以及cell name ,cell view既layout,把Output "Floating Shapes" into SPECIAL NETS Section勾上,OK即可。2)在要导出的layout界面选中PAD和prBoundary(shift+左键),快捷键C copy到空cell里,这时需要调整copy过来的object坐标,让两边prBoundary的坐标相同。我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?

m0_61544122的博客 2304

使用rabbitmq 实现延迟消费

rabbitmq 实现延迟队列 什么是延迟队列 延迟队列存储的对象肯定是对应的延时消息,所谓”延时消息”是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费。 比如以下场景:在订单系统中,一个用户下单之后通常有30分钟的时间进行支付,如果30分钟之内没有支付成功,那么这个订单将进行一场处理。这是就可以使用延时队列将订单信息发送到延时队列。 Ra...

zhuchunyan_aijia的博客 4948

AI绘画与医疗可视化:用AI生成医学插图的实践

医疗可视化是医学教育、临床沟通和学术研究的核心工具。传统医学插图依赖手工绘制或专业3D建模,存在制作周期长、成本高、更新迭代慢等问题。随着深度学习技术的发展,AI绘画工具(如Stable Diffusion、DALL-E)展现出强大的图像生成能力,但医疗领域对插图的解剖准确性、标注规范性和语义完整性有极高要求,通用AI模型难以直接应用。本文聚焦AI技术与医疗领域的交叉创新,系统阐述如何通过数据预处理、模型定制化训练和后处理校验,构建符合医疗标准的插图生成系统。

大模型应用工坊 1788

RabbitMQ消费端限流、消息超时、死信队列、延迟队列

RabbitMQ消费端限流、消息超时、死信队列、延迟队列

weixin_52634451的博客 1671

芒果YOLO11改进176:2025最新顶会论文|尺度动态损失函数Scale-based Dynamic Loss,即插即用|以减少标签不准确对损失函数稳定性的影响

芒果YOLO11改进186:2025最新顶会论文|尺度动态损失函数Scale-based Dynamic Loss,即插即用|以减少标签不准确对损失函数稳定性的影响

包括YOLOv5、YOLOv7、YOLOv8等模型改进 2126

万字长文,YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

YOLOv8 yaml 文件解析 | 一文搞定 YOLOv8 分类任务,检测任务,分割任务,关键点任务

Coding... 1万+

RabbitMQ系列之消费限流、TTL、死信队列、延迟队列

RabbitMQ高级特性 消费限流 什么是消费端限流 场景: 假设MQ服务器接收很多未处理的消息,这些消息会瞬间打在消费者客户端,当接收到如此巨量的消息客户端是无法处理的,所以就需要在MQ和消费者之间做个限流,在消费者进行消费时限制消费流量 解决方案: RabbitMQ提供了一种qos(服务质量保证)功能,在非自动确认消息的前提下,设置channel或queue的预处理流量,进而来限流,方法如下: void BasicQos(uint prefetchSize,ushort prefetchCount,

qq_38668544的博客 448

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

RabbitMQ的死信队列、延迟队列、消息的幂等性消费

死信队列、延迟队列、消息的幂等性消费 一、通过代码实现创建队列和交换机以及绑定 application.yml # 端口号 server: port: 8083 # rabbitmq配置 spring: rabbitmq: host: 192.168.31.129 代码实现 package com.hong.config; import org.springframework.amqp.core.*; import org.springframework.context.ann

qq_54605990的博客 257

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

RabbitMQ(三)SpringBoot整合,可靠性投递,死信队列,延迟队列,消费端限流,消息超时

SpringBoot整合,可靠性投递,死信队列,延迟队列,消费端限流,消息超时

爱喝星冰乐的博客 1743

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

【RabbitMQ】高级特性(消费端限流、过期时间、死信队列、延迟队列)

消费端限流 消费端限流是为了防止消息积压后,消费端一次拉取过多的消息而挂掉。 我们限制一个数字,其含义是:当所有的消息都被手动确认之后,消费者可以拉取的最大消息数。 核心配置: (1)在<rabbit:listener-container>中设置 prefetch="30" (2)消费端的确认模式一定是手动确认,即 acknowledge="manual" <rabbit:listener-container connection-factory="connectionFactory"

丧心病狂Loli控的博客 544

【SpringBoot】SpringBoot整合RabbitMQ消息中间件,实现延迟队列和死信队列

RabbitMQ的死信队列(Dead Letter Queue,DLQ)是一种特殊的队列,用于接收其他队列中的“死信”消息。所谓“死信”,是指满足一定条件而无法被消费者正确处理的消息,这些条件包括消息被拒绝、消息过期、消息达到最大重试次数等。当消息成为死信时,RabbitMQ会将其重新发送到指定的死信队列,而不是丢弃它们。这样做的好处是可以对死信进行分析和处理,例如记录日志、重新入队或者进一步处理。

qq_61024956的博客 9839

rabbitmq 延迟队列_rabbitmq死信队列,消息延迟消费

rabbitmq中如果消息被拒绝,或消息过期,或极端情况队列达到最大长度,这时消息就变成了死信,死信消息可以通过队列绑定死信交换器,从而将消息路由到死信交换器绑定的队列里。public static void main(String[] argv) throws Exception { ConnectionFactory factory = new ConnectionFactor...

weixin_39812577的博客 273

SpringBoot+RabbitMq 采用 TTL(延迟队列)+ DLX(死信队列)实现延迟消费

采用 TTL(延迟队列)+DLX(死信队列)实现延迟消费1、pom文件引入jar包2、yml 配置3、声明交换机、队列及绑定4、定义常量类5、发送消息6、消费消息   1、pom文件引入jar包   <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-a

STRANGE-P 的博客 765

详解RabbitMQ高级特性之延迟队列

详解RabbitMQ高级特性之延迟队列(基于TTL+死信队列实现延迟队列)。

. 3174

RabbitMQ(五)死信队列、延迟队列

死信队列、延迟队列

agululu的博客 4370

RabbitMQ 高级特性——延迟队列

RabbitMQ延迟队列

不能再留遗憾了的博客 1529
上一篇: Redis的两种持久化RDB和AOF(超详细)
下一篇: Sleuth,Zipkin集成rabbitmq和elasticsearch实战(分布式系统服务链追踪组件)
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值