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

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列

  • 问题发现
  • 问题解决
    • 方法一:只监听死信队列,在死信队列里面处理业务逻辑
    • 方法二:修改预取值

问题发现

最近再学习RabbitMQ过程中,看到关于死信队列内容:

来自队列的消息可以是 “死信”,这意味着当以下四个事件中的任何一个发生时,这些消息将被重新发布到 Exchange

  1. 使用 basic.rejectbasic.nackrequeue 参数设置为 false 的使用者否定该消息
  2. 消息由于每条消息的 TTL 而过期
  3. 队列超出了长度限制

之前的文章里面有讲解过TTL过期后不进入死信队列的疑惑和解决办法,然后上手去实践另一个死信队列的方法,结果又是一道坑等着我,示例代码如下:

默认自动应答模式

@Configuration
public class MQConfig {/*** 死信队列* @return*/@Beanpublic Queue deadQueue(){return new Queue("dead_queue");}/*** 死信队列交换机* @return*/@Beanpublic DirectExchange deadExchange(){return new DirectExchange("dead.exchange");}/*** 死信队列和死信交换机绑定* @return*/@Beanpublic Binding deadBinding(){return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead");}/*** 普通队列* @return*/@Beanpublic Queue queue(){
//          方法一
//        Queue normalQueue = new Queue("normal_queue");
//        normalQueue.addArgument("x-dead-letter-exchange", "dead.exchange"); // 死信队列
//        normalQueue.addArgument("x-dead-letter-routing-key", "dead"); // 死信队列routingKey
//        normalQueue.addArgument("x-max-length", 5);//设置队列最大长度
//        normalQueue.addArgument("x-overflow","reject-publish");//最近发布的消息将被丢弃
//        方法二return  QueueBuilder.durable("normal_queue").deadLetterExchange("dead.exchange").deadLetterRoutingKey("dead").maxLength(5) // 设置队列最大长度为5.build();}/*** 普通交换机* @return*/@Beanpublic DirectExchange normalExchange(){return new DirectExchange("normal.exchange");}/*** 普通队列和普通交换机绑定* @return*/@Beanpublic Binding binding(){return BindingBuilder.bind(queue()).to(normalExchange()).with("normal");}
}

监听普通队列消费方,示例代码如下:

@Component
@RabbitListener(queues = "normal_queue")
public class MQReceiver {private static final Logger log = LoggerFactory.getLogger(MQReceiver.class);@RabbitHandlerpublic void receive(String msg) {log.info("收到消息:"+msg);}
}

监听死信队列消费方,示例代码如下:

@Component
@RabbitListener(queues = "dead_queue")
public class MQReceiver2 {private static final Logger log = LoggerFactory.getLogger(MQReceiver2.class);@RabbitHandlerpublic void receive(String msg) {log.info("死信队列收到消息:{}",msg);}
}

发送方发送10条消息,示例代码如下:

@Component
public class MQSender {@Autowiredprivate RabbitTemplate template;public void send() {for (int i = 0; i < 10; i++) {String msg = "hello world_"+i;template.convertAndSend("normal.exchange", "normal", msg);}}
}

然后调用send()方法,执行结果如图:

在这里插入图片描述

按道理会将队列前面的5条消息进入死信队列,然后剩下的五条消息正常消费才对,我们检查一下队列是否设置成功,如图所示

在这里插入图片描述
设置没有问题,那就很懵逼了。。。

问题解决

我们先在页面上向普通队交换机发送10条消息,然后查看它的状态,如图所示:
在这里插入图片描述
超过5条消息就会放入死信队列中,如图所示:

.
然后再看一下,默认行为是从队列前面删除或死信消息,如图所示:

在这里插入图片描述
我们可以看到普通队列存放的是最后5条消息,前面的5条消息进入死信队列。也就是说,再没有进入普通消费者之前会将队列前面删除或死信消息(进入消费者之前将消息进行分配)。

方法一:只监听死信队列,在死信队列里面处理业务逻辑

这种做法也是网上大多数文章的一种处理方法(另外一种情况就是进入普通消费者,还没被消费完的情况下,消费者挂了,然后队列就会重新分配,将从队列前面删除或者进入死信队列),如图所示:

在这里插入图片描述

但是这些做法都是基于没有普通消费者监听的情况下进行的,感觉和我理解的略有偏差(应该是再有普通消费者监听和死信队列监听的情况下,发送消息时会对消息进行分配处理)。

发送方代码和配置的代码就不重复展示了(参考之前示例),监听死信队列(自动确认模式和手动确认模式都一样),示例代码如下:

@Component
@RabbitListener(queues = "dead_queue")
public class MQReceiver2 {private static final Logger log = LoggerFactory.getLogger(MQReceiver2.class);@RabbitHandlerpublic void receive(String msg,Message message,Channel channel) throws IOException {log.info("死信队列收到消息:{}",msg);channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}
}

调用send()方法,执行结果如图:

在这里插入图片描述
然后再死信队列里面处理业务逻辑即可。

方法二:修改预取值

再监听普通队列时抛异常或者手动拒绝重新进入队列,这两种方式都不能达到我想要的效果,我发现只要有普通消费方监听就会进入消费,然后我就在想是不是因为预期值的问题导致,可能我消息数量太少了,然后默认预期值太高导致消息直接进入消费,然后将预取值改为1自动确认模式,示例代码如下:

spring.rabbitmq.listener.simple.prefetch=1

发送方代码和配置的代码就不重复展示了(参考之前示例),监听普通队列,示例代码如下:

@Component
@RabbitListener(queues = "normal_queue")
public class MQReceiver {private static final Logger log = LoggerFactory.getLogger(MQReceiver.class);@RabbitHandlerpublic void receive(String msg) throws InterruptedException {log.info("收到消息:"+msg);// 模拟业务处理队列等待场景Thread.sleep(10000);}
}

监听死信队列,示例代码如下:

@Component
@RabbitListener(queues = "dead_queue")
public class MQReceiver2 {private static final Logger log = LoggerFactory.getLogger(MQReceiver2.class);@RabbitHandlerpublic void receive(String msg) {log.info("死信队列收到消息:{}",msg);}
}

调用send()方法,执行结果如图:

在这里插入图片描述
当然有的时候也不一定完全按照你设置的最大长度进入死信队列,有的时候消费速度太快(队列的第一个已经被消费了的情况),得看实际情况,至少可以确保再设置了大于队列最大长度时是可以正常进入死信队列的。归根结底:消息数量太少了

另外我们再来介绍一下溢出方式,一般默认情况下溢出方式为:drop-head(从队列前面删除或者进入死信队列),除此之外还有两种:

  • reject-publishreject-publish-dlx:最近发布的消息将被丢弃。reject-publishreject-publish-dlx 之间的区别在于 reject-publish-dlx 也是死信拒绝消息。

将配置的溢出模式改为reject-publish,示例代码如下:

@Configuration
public class MQConfig {/*** 死信队列* @return*/@Beanpublic Queue deadQueue(){return new Queue("dead_queue");}/*** 死信队列交换机* @return*/@Beanpublic DirectExchange deadExchange(){return new DirectExchange("dead.exchange");}/*** 死信队列和死信交换机绑定* @return*/@Beanpublic Binding deadBinding(){return BindingBuilder.bind(deadQueue()).to(deadExchange()).with("dead");}/*** 普通队列* @return*/@Beanpublic Queue queue() {
//          方法一
//        Queue normalQueue = new Queue("normal_queue");
//        normalQueue.addArgument("x-dead-letter-exchange", "dead.exchange"); // 死信队列
//        normalQueue.addArgument("x-dead-letter-routing-key", "dead"); // 死信队列routingKey
//        normalQueue.addArgument("x-max-length", 5);//设置队列最大长度
//        normalQueue.addArgument("x-overflow","reject-publish");//最近发布的消息将被丢弃
//        方法二return  QueueBuilder.durable("normal_queue").deadLetterExchange("dead.exchange").deadLetterRoutingKey("dead").maxLength(5) // 设置队列最大长度为5.overflow(QueueBuilder.Overflow.dropHead).build();}/*** 普通交换机* @return*/@Beanpublic DirectExchange normalExchange(){return new DirectExchange("normal.exchange");}/*** 普通队列和普通交换机绑定* @return*/@Beanpublic Binding binding(){return BindingBuilder.bind(queue()).to(normalExchange()).with("normal");}
}

重新创建队列,调用send()方法,如图所示:

在这里插入图片描述
由图可以,死信队列并不会受到消息。

然后我们再来看看将溢出模式设置为reject-publish-dlxQueueBuilder.Overflow没有该参数,手动定义),示例代码如下:

@Configuration
public class MQConfig {//忽略死信队列创建和绑定过程,参考前面示例.../*** 普通队列* @return*/@Beanpublic Queue queue() {Queue normalQueue = new Queue("normal_queue");normalQueue.addArgument("x-dead-letter-exchange", "dead.exchange"); // 死信队列normalQueue.addArgument("x-dead-letter-routing-key", "dead"); // 死信队列routingKeynormalQueue.addArgument("x-max-length", 5);//设置队列最大长度normalQueue.addArgument("x-overflow","reject-publish-dlx"); //最近发布的消息进入死信队列return normalQueue;}//忽略普通队列创建过程,参考前面示例...
}

重新创建队列,调用send()方法,如图所示:

在这里插入图片描述

如果你有更好的方法或者不同的理解,欢迎评论区交流。

相关文章:

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列

解决RabbitMQ设置x-max-length队列最大长度后不进入死信队列 问题发现问题解决方法一&#xff1a;只监听死信队列&#xff0c;在死信队列里面处理业务逻辑方法二&#xff1a;修改预取值 问题发现 最近再学习RabbitMQ过程中&#xff0c;看到关于死信队列内容&#xff1a; 来自队…...

【解决】chrome 谷歌浏览器,鼠标点击任何区域都是 Input 输入框的状态,能看到输入的光标

chrome 谷歌浏览器&#xff0c;鼠标点击任何区域都是 Input 输入框的状态&#xff0c;能看到输入的光标 今天打开电脑的时候&#xff0c;网页中任何文本的地方&#xff0c;只要鼠标点击&#xff0c;就会出现一个输入的光标&#xff0c;无论在哪个站点哪个页面都是如此。 我知道…...

使用python操作数据库

文章目录 一、问题背景二、安装python三、代码示例四、总结 一、问题背景 在日常开发过程中&#xff0c;随着项目进展和业务功能的迭代&#xff0c;我们需要对数据库的表结构进行修改&#xff0c;向部分表中追加字段&#xff0c;并对追加后的字段进行数据填充。但是如果需要追加…...

[Redis] 渐进式遍历+使用jedis操作Redis+使用Spring操作Redis

&#x1f338;个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 &#x1f3f5;️热门专栏: &#x1f9ca; Java基本语法(97平均质量分)https://blog.csdn.net/2301_80050796/category_12615970.html?spm1001.2014.3001.5482 &#x1f355; Collection与…...

排序----数据结构

Comparable Integer Double 默认情况下都是按照升序排列的 string 按照字母再ASCII码表中对应的数字升序进行排列 冒泡排序 时间复杂度O(x^2) 选择排序 时间复杂度O(x^2) 插入排序 时间复杂度O(x^2) 希尔排序 时间复杂度O(x) 归并排序 时间复杂度O(nlogn) 快速排序...

Crack道路裂缝检测数据集——目标检测数据集

【Crack道路裂缝检测数据集】共3684张。 目标检测数据集&#xff0c;标注文件为YOLO适用的txt格式。已划分为训练、验证集。 图片分辨率&#xff1a;224*224 类别&#xff1a;crack Crack道路裂缝检测数据集 数据集描述 该数据集是一个专门用于训练和评估基于YOLO&#xff0…...

10.3拉普拉斯金字塔

实验原理 拉普拉斯金字塔&#xff08;Laplacian Pyramid&#xff09;是一种图像表示方法&#xff0c;常被用于图像处理和计算机视觉领域。它是基于高斯金字塔的一种变换形式&#xff0c;主要用于图像融合、图像金字塔的构建等场景。下面简要介绍拉普拉斯金字塔的基本原理。 高…...

redis为什么不使用一致性hash

Redis节点间通信时&#xff0c;心跳包会携带节点的所有槽信息&#xff0c;它能以幂等方式来更新配置。如果采用 16384 个插槽&#xff0c;占空间 2KB (16384/8);如果采用 65536 个插槽&#xff0c;占空间 8KB (65536/8)。 今天我们聊个知识点为什么Redis使用哈希槽而不是一致性…...

Vue.js与Flask/Django后端配合

Vue.js与Flask/Django后端配合 在现代Web开发领域&#xff0c;前后端分离已成为一种流行的架构模式。Vue.js作为一款轻量级、高性能的前端框架&#xff0c;与Flask或Django这样的后端框架相结合&#xff0c;可以构建出强大且可扩展的Web应用。本文将详细介绍如何将Vue.js与Fla…...

ESP32 入门笔记02: ESP32-C3 系列( 芯片ESP32-C3FN4) (ESP-IDF + VSCode)

ESP32-C3 系列的 芯片 / 模组 / 开发板 ESP32-C3-DevKitM-1是乐鑫一款搭载 ESP32-C3-MINI-1 或 ESP32-C3-MINI-1U 模组的入门级开发板&#xff08;内置 ESP32-C3FH4 或 ESP32-C3FN4 芯片&#xff09;。 板上模组大部分管脚均已引出至两侧排针&#xff0c;可根据开发实际需求&a…...

Vue主题色实现

主题色实现 情境 配置平台支持多个主题色的选择&#xff0c;用户可通过在配置平台选择项目主题色。前端项目在骨架屏加载页面获取配置信息&#xff0c;设置项目主题色&#xff0c;实现同个项目不同主题色渲染的需求 实现 1.定义主题色变量 不同主题色根据不同js文件划分定…...

ChartLlama: A Multimodal LLM for Chart Understanding and Generation论文阅读

原文链接&#xff1a;https://arxiv.org/abs/2311.16483 代码与数据集&#xff1a;https://tingxueronghua.github.io/ChartLlama/ 本文启发&#xff1a;文章提出利用GPT-4合成大量图表数据&#xff0c;这些数据包含各种图表类型&#xff0c;包含丰富的instruction data。然后…...

ByteCinema(1):用户的登录注册

文章目录 主要功能生成图形验证码redis滑动窗口操作限流0.限流设计的必要性1.原理2.代码&#xff08;邮箱发验证码为例&#xff09;3. 问题与解决高并发环境下redis操作的原子性过时数据的积累 续约token实现长期登录0.设计的出发点1.前置知识:JWT什么是 JWT&#xff1f;JWT 的…...

电力电网电线变电站输电线绝缘子无人机类数据集/农业植物病虫害类数据集/光伏板/工程煤矿矿场类数据集/道路类数据集

电力电网电线变电站输电线红外缺陷类数据集 传送门链接&#xff1a; 1.电线覆盖物检测数据集 气球风筝鸟巢 1300张 voc yol-CSDN博客 2.变电站可见光缺陷数据集数据集包含8376张巡检图像&#xff0c;带xml标签&#xff0c;共包含17类巡检标签!具体缺陷分类见下图&#xff01…...

深度学习之表示学习 - 引言篇

序言 在数据爆炸的今天&#xff0c;如何从纷繁复杂的信息中抽取有价值的知识&#xff0c;成为了人工智能领域亟待解决的核心问题。深度学习&#xff0c;作为机器学习的一个重要分支&#xff0c;以其强大的特征表示能力和自动化学习特性&#xff0c;引领了这场数据革命的浪潮。…...

Linux驱动开发 ——架构体系

只读存储器&#xff08;ROM&#xff09; 1.作用 这是一种非易失性存储器&#xff0c;用于永久存储数据和程序。与随机存取存储器&#xff08;RAM&#xff09;不同&#xff0c;ROM中的数据在断电后不会丢失&#xff0c;通常用于存储固件和系统启动程序。它的内容在制造时或通过…...

Django一分钟:lookupAPI详解,使用django orm生成高效的WHERE子句

一、Lookup API概述 Lookup API是Django用于构建数据库查询WHERE子句的API。 Lookup API的核心包含两部分&#xff1a; RegisterLookupMixin&#xff1a;为子类提供注册lookup的方法Query Expression API&#xff1a;一个接口&#xff0c;规定了可以被注册为lookup的类需要实…...

信息安全工程师(8)网络新安全目标与功能

前言 网络新安全目标与功能在当前的互联网环境中显得尤为重要&#xff0c;它们不仅反映了网络安全领域的最新发展趋势&#xff0c;也体现了对网络信息系统保护的不断加强。 一、网络新安全目标 全面防护与动态应对&#xff1a; 目标&#xff1a;建立多层次、全方位的网络安全防…...

返利机器人在电商返利系统中的负载均衡实现

返利机器人在电商返利系统中的负载均衡实现 大家好&#xff0c;我是微赚淘客返利系统3.0的小编&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天我们来聊一聊如何在电商返利系统中实现返利机器人的负载均衡&#xff0c;尤其是在面对高并发和大量…...

MATLAB中typecast函数用法

目录 语法 说明 示例 将整数转换为相同存储大小的无符号整数 将 8 位整数转换为单精度 将 32 位整数转换为 8 位整数 将 8 位整数转换为 16 位整数 提示 typecast函数的功能是在不更改基础数据的情况下转换数据类型。 语法 Y typecast(X,type) 说明 Y typecast(X,…...

终极QR码修复指南:如何用QrazyBox免费恢复损坏的二维码

终极QR码修复指南&#xff1a;如何用QrazyBox免费恢复损坏的二维码 【免费下载链接】qrazybox QR Code Analysis and Recovery Toolkit 项目地址: https://gitcode.com/gh_mirrors/qr/qrazybox 你是否曾遇到过重要的二维码因为打印模糊、水渍污染或物理磨损而无法扫描&a…...

Python 3 简介

Python 3 简介 引言 Python 是一种广泛使用的编程语言,以其简洁的语法和强大的库支持而闻名。Python 3 是 Python 编程语言的最新主要版本,自 2008 年发布以来,它已经成为了许多开发者和企业首选的编程语言之一。本文将简要介绍 Python 3 的特点、应用领域以及学习资源。 …...

AMD Ryzen SMU Debug Tool完整指南:轻松掌握硬件级调试的5个关键步骤

AMD Ryzen SMU Debug Tool完整指南&#xff1a;轻松掌握硬件级调试的5个关键步骤 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地…...

86、【Agent】【OpenCode】bash 工具提示词(完结)

【声明】本博客所有内容均为个人业余时间创作&#xff0c;所述技术案例均来自公开开源项目&#xff08;如Github&#xff0c;Apache基金会&#xff09;&#xff0c;不涉及任何企业机密或未公开技术&#xff0c;如有侵权请联系删除 背景 上篇 blog 【Agent】【OpenCode】bash 工…...

告别繁琐操作:用VSCode插件‘Open in Browser’和‘CSS Peek’打造流畅的实时预览调试工作流

极速开发实战&#xff1a;VSCode插件组合拳实现HTML/CSS无缝调试 每次修改完CSS样式都要手动切换到浏览器刷新页面&#xff1f;在庞大的代码库中寻找某个CSS定义像大海捞针&#xff1f;这些问题困扰着无数前端开发者。今天我们将解锁VSCode中两个看似简单却威力巨大的插件——O…...

Python小白也能学会!3个月蜕变AI应用开发者的收藏秘籍

本文针对程序员&#xff0c;特别是只会CRUD的开发者&#xff0c;提供了学习大模型的实用路径。文章强调大模型应用开发是“低门槛、高上限”的方向&#xff0c;并给出了一个12步学习路线&#xff0c;涵盖Python基础、Transformer理解、提示词工程、RAG等&#xff0c;以及LangCh…...

戴尔G15散热终极控制:开源TCC-G15高效替代方案完全指南

戴尔G15散热终极控制&#xff1a;开源TCC-G15高效替代方案完全指南 【免费下载链接】tcc-g15 Thermal Control Center for Dell G15 - open source alternative to AWCC 项目地址: https://gitcode.com/gh_mirrors/tc/tcc-g15 对于戴尔G15笔记本用户而言&#xff0c;过热…...

告别踩坑!手把手教你用Cobalt Strike 4.7在Kali Linux上快速搭建团队服务器并上线第一台主机

Kali Linux环境下Cobalt Strike 4.7团队服务器部署与主机上线实战指南 在渗透测试和红队演练中&#xff0c;Cobalt Strike作为一款成熟的商业框架&#xff0c;其团队协作功能和丰富的攻击模拟能力备受安全从业者青睐。本文将基于Kali Linux系统&#xff0c;详细解析Cobalt Stri…...

QGIS连接天地图最新指南:搞定Token和Header,解决加载失败问题

QGIS连接天地图最新指南&#xff1a;搞定Token和Header&#xff0c;解决加载失败问题 天地图作为国内权威的地理信息服务&#xff0c;在QGIS中的集成使用一直是GIS从业者的高频需求。但最近不少用户反馈&#xff0c;按照网上流传的旧教程配置后&#xff0c;天地图服务在QGIS中…...

2026软考高级系统架构设计师预测试卷(二)

2026软考高级系统架构设计师预测试卷(二) 编制说明:本试卷为第二套预测卷,侧重不同考点角度,与第一套试卷不重复。 考试结构: 科目一:综合知识(75道单选题,每题1分,满分75分,合格线45分) 科目二:案例分析(1道必答+4选2,共答3道,满分75分,合格线45分) 科目三…...