当前位置: 首页 > news >正文

浅析RabbitMQ死信队列

原文首发于公众号【CSJerry】
在这里插入图片描述

在现代分布式系统中,消息队列扮演着至关重要的角色。它们可以实现应用程序之间的异步通信,并确保数据的可靠传输和处理。而在这个领域中,RabbitMQ作为一种强大而受欢迎的消息队列解决方案,具备了高效、可靠和灵活的特性。

然而,即使使用了RabbitMQ,我们仍然会遇到一些不可预料的情况,例如消费者无法处理某些消息、消息过期或者队列溢出等。为了解决这些问题,RabbitMQ引入了死信队列(Dead Letter Queue)的概念,为开发人员提供了一种有效的错误处理机制。

那么,究竟什么是死信队列呢?

本文结合Spring Boot使用RabbitMQ的死信队列,着重从是什么、为什么、怎么用几个方面对死信队列进行简单介绍。

1. 是什么:

  • 死信队列(Dead Letter Queue)是一种特殊的消息队列,用于存储无法被消费的消息。
  • 当消息满足某些条件无法被正常消费时,将被发送到死信队列中进行处理。
  • 死信队列提供了一种延迟处理、异常消息处理等场景的解决方案。

2. 为什么

  • 用来处理消费者无法正确处理的消息,避免消息丢失或积压
  • 实现延迟消息处理,例如订单超时未支付,可以将该消息发送到死信队列,然后再进行后续处理。
  • 用于实现消息重试机制,当消费者处理失败时,将消息重新发送到死信队列进行重试。
  • 提高了系统的可伸缩性和容错性,能够应对高并发和异常情况。

3. 怎么用

  1. 在Spring Boot中配置和使用死信队列:
    • 首先,在pom.xml文件中添加RabbitMQ的依赖项。
    • 然后,在application.properties文件中配置RabbitMQ连接信息。
    • 接下来,创建生产者和消费者代码,并通过注解将队列和交换机进行绑定。
    • 在队列的声明中添加死信队列的相关参数,如x-dead-letter-exchangex-dead-letter-routing-key等。
    • 最后,在消费者中编写处理消息的逻辑,包括对异常消息进行处理,并设置是否重新发送到死信队列。

简而言之,死信队列可以认为是一个正常队列的备用队列(或者说是兜底队列),当正常队列的消息无法消费的时候mq会重新把该消息发送到死信交换机,由死信交换机根据路由键将消息投递到备用队列,启动服务备用方案。

消息从正常队列到死信队列的三种情况:

1、消息被否定确认使用 channel.basicNackchannel.basicReject ,并且此时requeue 属性被设置为false

2、消息在队列中的时间超过了设置的TTL())时间。

3、消息数量超过了队列的容量限制()。

当一个队列中的消息满足上述三种情况任一个时,改消息就会从原队列移至死信队列,若改队列没有绑定死信队列则消息被丢弃。

4. 实战

以下是一个简单的Spring Boot集成RabbitMQ的死信队列示例代码:

  • 配置
spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=rabbit
spring.rabbitmq.password=123456
# 开启消费者手动确认
spring.rabbitmq.listener.type=direct# 发送到队列失败时的手动处理
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.publisher-returns=true# 发送到交换机手动确认
spring.rabbitmq.publisher-confirm-type=simple
  • 配置类
@Configuration
@Slf4j
public class RabbitCof {@Resourceprivate MqKeys mqKeys;@Bean("normalQueue")public Queue normalQueue() {/*** 为普通队列绑定交换机*/Map<String, Object> args = new HashMap<>();args.put("x-dead-letter-exchange", mqKeys.DIE_EXCHANGE);args.put("x-dead-letter-routing-key", mqKeys.DIE_ROUTING_KEY);args.put("x-message-ttl", 1000); // 队列中的消息未被消费则1秒后过期return new Queue(mqKeys.NORMAL_QUEUE, true, false, false, args);}@Bean("normalExchange")public Exchange normalExchange() {return new DirectExchange(mqKeys.NORMAL_EXCHANGE);}@Bean("normalBind")public Binding normalBinding(@Qualifier("normalQueue") Queue normalQueue, @Qualifier("normalExchange") Exchange normalExchange) {return BindingBuilder.bind(normalQueue).to(normalExchange).with(mqKeys.ROUTING_KEY).noargs();}/*** 死信队列* @return*/@Bean("dieQueue")public Queue dlQueue() {return new Queue(mqKeys.DIE_QUEUE, true, false, false);}/*** 死信交换机* @return*/@Bean("dieExchange")public Exchange dlExchange() {return new DirectExchange(mqKeys.DIE_EXCHANGE);}@Bean("dieBind")public Binding dlBinding(@Qualifier("dieQueue") Queue dlQueue, @Qualifier("dieExchange") Exchange dlExchange) {return BindingBuilder.bind(dlQueue).to(dlExchange).with(mqKeys.DIE_ROUTING_KEY).noargs();}@Resourceprivate ConnectionFactory connectionFactory;@Beanpublic RabbitTemplate rabbitTemplate() {RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);/*** 消费者确认收到消息后,手动ack回调处理* spring.rabbitmq.publisher-confirm-type=simple*/rabbitTemplate.setConfirmCallback((CorrelationData correlationData, boolean ack, String cause)->{if(!ack) {log.info("消息投递到交换机失败,correlationData={} ,ack={}, cause={}", correlationData == null ? "null" : correlationData.getId(), ack, cause);} else {log.info("消息成功投递到交换机,correlationData={} ,ack={}, cause={}", correlationData == null ? "null" : correlationData.getId(), ack, cause);}});/*** 消息投递到队列失败回调处理* spring.rabbitmq.listener.direct.acknowledge-mode=manual* spring.rabbitmq.publisher-returns=true*/rabbitTemplate.setReturnsCallback((returnedMessage)->{Message message = returnedMessage.getMessage();log.error("分发到到队列失败, body->{}", message.getBody());});return rabbitTemplate;}
}
  • 生产者类
@Component
public class Producer {@Resourceprivate  MqKeys mqKeys;@Resourceprivate RabbitTemplate rabbitTemplate;public void sendMessage(String message) {rabbitTemplate.convertAndSend(mqKeys.NORMAL_EXCHANGE, mqKeys.ROUTING_KEY, message);}
}
  • 消费者类
@Component
@RabbitListener(queues = "normal.queue")
@Slf4j
public class Consumer {@RabbitHandlerpublic void handleMessage(String data, Message message, Channel channel) {boolean success = false;int retryCount = 3;System.out.println(message.toString());long deliveryTag = message.getMessageProperties().getDeliveryTag();while (!success && retryCount-- > 0){try {// 处理消息log.info("收到消息: {}, deliveryTag = {}", data, deliveryTag);// 正常处理完毕,手动确认,此处不确认让他进入死信队列
//                success = true;
//                channel.basicAck(deliveryTag, false);Thread.sleep(3 * 1000L);}catch (Exception e){log.error("程序异常:{}", e.getMessage());}}// 达到最大重试次数后仍然消费失败if(!success){try {log.info("move to die queue");// 手动拒绝,移至死信队列/***deliveryTag – the tag from the received AMQP.Basic.GetOk or AMQP.Basic.Delivermultiple – true to reject all messages up to and including the supplied delivery tag; false to reject just the supplied delivery tag.requeue – true if the rejected message(s) should be requeued rather than discarded/dead-lettered*/channel.basicNack(deliveryTag, false, false);} catch (IOException e) {e.printStackTrace();}}}
}

以上代码演示了如何在Spring Boot中配置一个普通队列和一个死信队列,然后通过生产者发送消息到普通队列,在消费者中处理消息,并模拟了当发生异常时将消息重新发送到死信队列。

参考连接

  • [rabbit 官网]Dead Letter Exchanges — RabbitMQ

  • 具体代码仓库

相关文章:

浅析RabbitMQ死信队列

原文首发于公众号【CSJerry】 在现代分布式系统中&#xff0c;消息队列扮演着至关重要的角色。它们可以实现应用程序之间的异步通信&#xff0c;并确保数据的可靠传输和处理。而在这个领域中&#xff0c;RabbitMQ作为一种强大而受欢迎的消息队列解决方案&#xff0c;具备了高…...

ELK 企业级日志分析系统(ElasticSearch、Logstash 和 Kiabana 详解)

目录 一.ELK简介 1.1ELK的概述 1.2ELK的组成 1.2.1 ElasticSearch 1.2.2 Logstash 1.2.3 Kibana 1.2.4 小总结 1.3可以添加其他组件 1.4filebeat 结合 logstash 带来好处 1.5日志处理的步骤 二.Elasticsearch 2.1Elasticsearch概述 2.2Elasticsearch核心概念 2.2.1接近…...

数学建模—多元线性回归分析

第一部分&#xff1a;回归分析的介绍 定义&#xff1a;回归分析是数据分析中最基础也是最重要的分析工具&#xff0c;绝大多数的数据分析问题&#xff0c;都可以使用回归的思想来解决。回归分析的人数就是&#xff0c;通过研究自变量X和因变量Y的相关关系&#xff0c;尝试去解释…...

win10 64位 vs2017 qt5.12.6 pcl1.9.1 vtk8.1.1配置安装步骤

由于我电脑中有 QT5.12.6 VS2017&#xff0c;就不介绍怎么安装了&#xff0c;只介绍cmake&#xff0c;pcl及vtk的配置步骤 为了便于后续QT的调用&#xff0c;以下所有安装路径中均不能出现中文及空格等 PCL自带VTK是不完整的&#xff0c;所以需要下载VTK源码进行重新编译使其…...

【项目 计网1】4.1 网络结构模式 4.2MAC地址、IP地址、端口

文章目录 第四章 Linux网络编程4.1 网络结构模式C/S结构&#xff08;client-server&#xff09;B/S结构&#xff08;Browser/Server&#xff0c;浏览器/服务器模式&#xff09; 4.2 4.3MAC地址、IP地址、端口&#xff08;1&#xff09;&#xff08;2&#xff09;MAC地址IP地址(…...

uni-app:分页实现多选功能

效果 代码解析 一、标签-列表 <view class"item_all" v-for"(item, index) in info" :key"index"><view class"position parameter-info text-over" :class"{checked_parameter: item.checked}" :data-id"i…...

问道管理:沪指窄幅震荡跌0.18%,有色、汽车等板块走低

3日早盘&#xff0c;沪指盘中窄幅震动下探&#xff0c;创业板逆市上扬&#xff1b;两市半日成交不足5000亿元&#xff0c;北向资金净卖出超15亿元。 到午间收盘&#xff0c;沪指跌0.18%报3255.88点&#xff0c;深成指跌0.23%&#xff0c;创业板指涨0.2%&#xff1b;两市算计成交…...

Kotlin 协程与 Flow

简介 Kotlin的Flow 是 Kotlin 在异步编程方面的一个重要组件&#xff0c;它提供了一种声明式的、可组合的、基于协程的异步编程模型。Flow 的设计灵感来自于 Reactive Streams、RxJava、Flux 和其他异步编程库&#xff0c;但它与 Kotlin 协程无缝集成&#xff0c;并提供了一种更…...

设备管理系统与物联网的融合:实现智能化设备监控和维护

在数字化时代&#xff0c;设备管理系统和物联网技术的融合为工业企业带来了巨大的变革和创新。本文将探讨设备管理系统与物联网的融合&#xff0c;重点介绍设备健康管理平台在实现智能化设备监控和维护方面的关键作用和优势。 一、设备管理系统与物联网的融合 随着物联网技术的…...

三、从官方源码精简出第1个FreeRTOS

1、官方源码下载 (1)进入FreeRTOS官网&#xff1a;FreeRTOS官网 (2)点击下载FreeRTOS。 (3)选择待示例的项目进行下载。 2、删减目录 (1)下载后解压的FreeRTOS文件如下图所示。 (2)删除下图中红框勾选的文件。 (3)删除"FreeRTOSv202212.01\FreeRTOS\Demo"目录下用…...

__call__函数的用法

__call__的用法 在 Python 中&#xff0c;类可以通过定义特殊方法 call 来使其实例对象可调用&#xff0c;就像调用普通的函数一样。当你在实例对象后面加上括号并传递参数时&#xff0c;Python 会自动调用这个对象的 call 方法。这使得你可以将类的实例对象当作函数来使用。 下…...

golang定时任务库cron实践

简介 cron一个用于管理定时任务的库&#xff0c;用 Go 实现 Linux 中crontab这个命令的效果。之前我们也介绍过一个类似的 Go 库——gron。gron代码小巧&#xff0c;用于学习是比较好的。但是它功能相对简单些&#xff0c;并且已经不维护了。如果有定时任务需求&#xff0c;还…...

Julia 流程控制

流程控制语句通过程序设定一个或多个条件语句来实现。在条件为 true 时执行指定程序代码&#xff0c;在条件为 false 时执行其他指定代码。 Julia 提供了大量的流程控制语句&#xff1a; 复合表达式&#xff1a;begin 和 ;。 条件表达式&#xff1a;if-elseif-else 和 ?: (三…...

问题解决方案

前端开发 1、npm安装的时候老是卡住 reify:rxjs: timing reifyNode:node_modules/vue/cli/node_modules 查看当前使用的那个镜像 nrm lsnpm ---------- https://registry.npmjs.org/yarn --------- https://registry.yarnpkg.com/cnpm --------- https://r.cnpmjs.org/taobao …...

kubernetes基于helm部署gitlab-operator

kubernetes基于helm部署gitlab-operator 这篇博文介绍如何在 Kubernetes 中使用helm部署 GitLab-operator。 先决条件 已运行的 Kubernetes 集群负载均衡器&#xff0c;为ingress-nginx控制器提供EXTERNAL-IP&#xff0c;本示例使用metallb默认存储类&#xff0c;为gitlab p…...

ChatGPT在在线客服和呼叫中心中的应用如何?

ChatGPT在在线客服和呼叫中心领域中有广泛的应用潜力&#xff0c;可以帮助企业提供更高效、个性化和满意度更高的客户服务体验。以下是详细的讨论&#xff1a; **1. 自动化客服&#xff1a;** ChatGPT可以用于自动化客服流程&#xff0c;通过自动回复用户的常见问题和查询&…...

C++多线程环境下的单例类对象创建

使用C无锁编程实现多线程下的单例模式 贺志国 2023.8.1 在多线程环境下创建一个类的单例对象&#xff0c;要比单线程环境下要复杂很多。下面介绍在多线程环境下实现单例模式的几种方法。 一、尺寸较小的类单例对象创建 如果待创建的单例类SingletonForMultithread内包含的成…...

“深入解析JVM内部机制:从字节码到垃圾回收“

标题&#xff1a;深入解析JVM内部机制&#xff1a;从字节码到垃圾回收 摘要&#xff1a;本文将从字节码生成、类加载、运行时数据区域和垃圾回收等方面深入解析JVM的内部机制&#xff0c;并通过示例代码展示其工作原理和实践应用。 正文&#xff1a; 一、字节码生成 JVM是基…...

音频系统项目与音频算法研究方向分类

+我V hezkz17进数字音频系统研究开发交流答疑群(课题组) 音频系统项目与音频算法研究方向分类 一 音频系统项目产品分类 1 收音机,数字收音机,复读机 2 耳机,蓝牙耳机,TWS蓝牙耳机, 3 立体声音箱,AI智能音箱, 4 音频功放,车载功放, 5 音响,普通音响,Soundbar音响…...

单例模式和工厂模式

目录 今日良言&#xff1a;关关难过关关过&#xff0c;步步难行步步行 一、单例模式 1.饿汉模式 2.懒汉模式 二、工厂模式 今日良言&#xff1a;关关难过关关过&#xff0c;步步难行步步行 一、单例模式 首先来解释一下&#xff0c;什么是单例模式。 单例模式也就是单个…...

OpenClaw v2026.4.1 深度剖析报告:任务系统、协作生态与安全范式的全面跃迁

摘要本报告旨在对 OpenClaw 于 2026 年 4 月 2 日发布的 v2026.4.1 版本进行一次全面、深入、颗粒度至极的技术与战略解构。该版本由 30 余位社区贡献者共同完成&#xff0c;标志着 OpenClaw 在经历了 3 月份“架构重塑”与“安全加固”的底层革命后&#xff0c;正式迈入“体验…...

MySQL 中 count(*)、count(1) 和 count(字段名) 有什么区别?

一、快速结论&#xff08;先看结论再看分析&#xff09;方式作用效率一句话总结count(*)统计所有行数⭐⭐⭐⭐ 最高我是专业的&#xff01;我为统计而生count(1)统计所有行数⭐⭐⭐⭐ 同样高效我是 count(*) 的马甲兄弟count(列名)统计该列非 NULL 的行数⭐⭐⭐ 较慢我挑剔&…...

探索NextDNS Config:优化你的DNS配置以提升网络性能

探索NextDNS Config&#xff1a;优化你的DNS配置以提升网络性能 是一个开源项目&#xff0c;旨在帮助用户轻松地管理并优化其设备上的NextDNS设置。该项目由Yokoffing开发&#xff0c;并提供了多种平台&#xff08;包括路由器、Android和iOS&#xff09;的配置文件&#xff0c;…...

终极指南:web3.py Gas价格策略如何优化以太坊交易成本

终极指南&#xff1a;web3.py Gas价格策略如何优化以太坊交易成本 【免费下载链接】web3.py A python interface for interacting with the Ethereum blockchain and ecosystem. 项目地址: https://gitcode.com/gh_mirrors/we/web3.py web3.py 作为以太坊区块链的 Pytho…...

SearXNG 高级部署方案:自带反向代理的专家级配置

SearXNG 高级部署方案&#xff1a;自带反向代理的专家级配置 【免费下载链接】searxng-docker The docker-compose files for setting up a SearXNG instance with docker. 项目地址: https://gitcode.com/gh_mirrors/se/searxng-docker 想要快速搭建一个安全、隐私保护…...

关于准备智慧校园建设专项资金申报材料的参考清单

✅作者简介&#xff1a;合肥自友科技 &#x1f4cc;核心产品&#xff1a;智慧校园平台(包括教工管理、学工管理、教务管理、考务管理、后勤管理、德育管理、资产管理、公寓管理、实习管理、就业管理、离校管理、科研平台、档案管理、学生平台等26个子平台) 。公司所有人员均有多…...

SpringBoot整合MQTT实战:从零到一构建物联网消息通信

1. 为什么选择SpringBoot整合MQTT&#xff1f; 物联网项目开发中&#xff0c;设备与服务器的通信就像快递员送货上门。MQTT协议就是这个快递员&#xff0c;而SpringBoot就是你家门口的智能快递柜。两者结合能让设备数据像包裹一样准时送达&#xff0c;还不会丢件。 我去年做过一…...

1989-2017 年泛北极和北方地区冬季原位土壤 CO2 通量的综合分析

Synthesis of Winter In Situ Soil CO2 Flux in pan-Arctic and Boreal Regions, 1989-2017 简介 本数据集综合了来自泛北极和北方多年冻土区多个地点的冬季&#xff08;9 月至次年 4 月&#xff09;原位土壤 CO₂通量测量数据。这些原位数据来自 1989 年至 2017 年间开展的 …...

OpenClaw+千问3.5-9B学习助手:自动整理课程笔记与生成测验

OpenClaw千问3.5-9B学习助手&#xff1a;自动整理课程笔记与生成测验 1. 为什么需要AI学习助手&#xff1f; 去年备考PMP认证时&#xff0c;我每天需要处理3-4小时的视频课程。最痛苦的环节不是听课&#xff0c;而是课后整理&#xff1a;暂停视频记录重点、梳理知识框架、制作…...

收藏备用!小白程序员必看:从基础到进阶,彻底吃透Prompt与提示工程

本文将从基础入门到进阶实操&#xff0c;全面拆解Prompt的核心知识点&#xff0c;涵盖概念定义、分类维度、核心要素、工作原理&#xff0c;以及可直接套用的实用提示工程方法。全程避开晦涩术语&#xff0c;用程序员易懂的表述搭配具体案例&#xff0c;适配刚接触大模型的小白…...