19.延迟队列优化
问题
前面所讲的延迟队列有一个不足之处,比如现在有一个需求需要延迟半个小时的消息,那么就只有添加一个新的队列。那就意味着,每新增一个不同时间需求,就会新创建一个队列。
解决方案
应该讲消息的时间不要跟队列绑定,应该交给消息的生产者,由发送消息来指定延迟时间。这样就可以定义个通用的队列。
方案图

代码
配置类
package com.xkj.org.config;import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.HashMap;
import java.util.Map;/*** TTL队列,配置文件代码*/
@Configuration
public class TtlQueueConfig {//普通交换机public static final String X_EXCHANGE = "X";//死信交换机public static final String Y_HEAD_LETTER_EXCHANGE = "Y";//普通队列public static final String QUEUE_A = "QA";public static final String QUEUE_B = "QB";public static final String QUEUE_C = "QC";//死信队列public static final String DEAD_LETTER_QUEUE = "QD";/*** 声明普通交换机X,bean的别名xExchange* @return*/@Bean("xExchange")public DirectExchange xExchange() {return new DirectExchange(X_EXCHANGE);}/*** 声明死信交换机Y,bean的别名yExchange* @return*/@Bean("yExchange")public DirectExchange yExchange() {return new DirectExchange(Y_HEAD_LETTER_EXCHANGE);}/*** 声明普通队列QA* @return*/@Bean("queueA")public Queue queueA() {Map<String, Object> arguments = new HashMap<>(3);//设置死信交换机arguments.put("x-dead-letter-exchange", Y_HEAD_LETTER_EXCHANGE);//声明死信的routingeyarguments.put("x-dead-letter-routing-key", "YD");//设置消息过期时间ttl为10sarguments.put("x-message-ttl", 10000);return QueueBuilder.durable(QUEUE_A).withArguments(arguments).build();}/*** 声明普通队列QB* @return*/@Bean("queueB")public Queue queueB() {Map<String, Object> arguments = new HashMap<>(3);//设置死信交换机arguments.put("x-dead-letter-exchange", Y_HEAD_LETTER_EXCHANGE);//声明死信的routingKeyarguments.put("x-dead-letter-routing-key", "YD");//设置消息过期时间ttl为40sarguments.put("x-message-ttl", 40000);return QueueBuilder.durable(QUEUE_B).withArguments(arguments).build();}/*** 声明普通队列QC* @return*/@Bean("queueC")public Queue queueC() {Map<String, Object> arguments = new HashMap<>(2);//设置死信交换机arguments.put("x-dead-letter-exchange", Y_HEAD_LETTER_EXCHANGE);//设置死信的routingKeyarguments.put("x-dead-letter-routing-key", "YD");//这里不要设置TTL时间return QueueBuilder.durable(QUEUE_C).withArguments(arguments).build();}/*** 声明死信队列QD* @return*/@Bean("queueD")public Queue queueD() {return QueueBuilder.durable(DEAD_LETTER_QUEUE).build();}/*** 将队列QA绑定到交换机X上,指定routingKey为XA* @param queueA* @param xExchange* @return*/@Beanpublic Binding queueABindingX(@Qualifier("queueA") Queue queueA, @Qualifier("xExchange")DirectExchange xExchange) {return BindingBuilder.bind(queueA).to(xExchange).with("XA");}/*** 将队列QB绑定到交换机X上,指定routingKey为XB* @param queueB* @param xExchange* @return*/@Beanpublic Binding queueBBindingX(@Qualifier("queueB") Queue queueB, @Qualifier("xExchange") DirectExchange xExchange) {return BindingBuilder.bind(queueB).to(xExchange).with("XB");}/*** 将队列QC绑定到交换机X上,指定routingKey为XC* @param queueC* @param xExchange* @return*/@Beanpublic Binding queueCBindingX(@Qualifier("queueC") Queue queueC, @Qualifier("xExchange") DirectExchange xExchange) {return BindingBuilder.bind(queueC).to(xExchange).with("XC");}/*** 将队列QD绑定到交换机Y上,指定routingKey为YD* @param queueD* @param yExchange* @return*/@Beanpublic Binding queueDBindingY(@Qualifier("queueD") Queue queueD, @Qualifier("yExchange") DirectExchange yExchange) {return BindingBuilder.bind(queueD).to(yExchange).with("YD");}}
生产者
package com.xkj.org.controller;import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Date;/*** 消息生产者*/
@Slf4j
@RestController
@RequestMapping("/ttl")
@Api(tags = "消息生产者", description = "消息生产者控制器")
public class MessageController {@Autowiredprivate RabbitTemplate rabbitTemplate;@ApiOperation("消息发送测试")@GetMapping("/sendMsg/{msg}")public void sendMsg(@ApiParam(value = "发送的消息内容", required = true) @PathVariable("msg") String message) {log.info("当前时间{},发送一条消息给两个队列:{}", new Date().toString(), message);rabbitTemplate.convertAndSend("X", "XA", "ttl=10s的消息:" + message);rabbitTemplate.convertAndSend("X", "XB", "ttl=40s的消息:" + message);}@ApiOperation("发送带过期时间的消息")@GetMapping("/sendExpiredMsg/{msg}/{ttl}")public void sendMsgExpired(@ApiParam(value = "消息内容", required = true)@PathVariable("msg") String message,@ApiParam(value = "ttl时间", required = true)@PathVariable("ttl") String ttlTime) {log.info("当前时间{},发送一条消息给队列QC:{},ttl={}", new Date().toString(), message, ttlTime);rabbitTemplate.convertAndSend("X", "XC", message, msg -> {msg.getMessageProperties().setExpiration(ttlTime);return msg;});}}
消费者
package com.xkj.org.listener;import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;import java.util.Date;/*** 消费者*/
@Slf4j
@Componentpublic class DeadLetterQueueConsumer {@RabbitListener(queues = "QD")public void receiveD(Message message, Channel channel) throws Exception {String msg = new String(message.getBody(), "UTF-8");log.info("当前时间:{},收到死信队列的消息:{}", new Date().toString(), msg);}
}
问题
改造代码后,发送两条消息,一条ttl为2s,另一条ttl为10s。ttl为2s的消息也要等到10s后才会收到。

原因
因为队列是先进先出的,消息需要排队,第一条消息10s才会发出去,第二条消息2s发出去,但是由于10s的消息没有发出去,2s的消息就只有等待。
解决方案
使用rabbitmq插件来解决,请看后续博文。
相关文章:
19.延迟队列优化
问题 前面所讲的延迟队列有一个不足之处,比如现在有一个需求需要延迟半个小时的消息,那么就只有添加一个新的队列。那就意味着,每新增一个不同时间需求,就会新创建一个队列。 解决方案 应该讲消息的时间不要跟队列绑定…...
P10477 Subway tree systems 题解,c++ 树相关题目
题目 poj 链接 洛谷链接 n n n 组数据,每组数据给定两个 01 01 01 串(长度不超过 3000 3000 3000),意思如下: 对于每一个 0 0 0,代表该节点有一个子节点,并前往该子节点。对于每一个 1 1 …...
18.jdk源码阅读之CopyOnWriteArrayList
1. 写在前面 CopyOnWriteArrayList 是 Java 中的一种线程安全的 List 实现,基于“写时复制”(Copy-On-Write)机制。下面几个问题大家可以先思考下,在阅读源码的过程中都会解答: CopyOnWriteArrayList 适用于哪些场景…...
美股:AMD展现乐观前景,挑战AI加速器市场霸主
在科技行业的激烈竞争中,AMD公司近期发布了对当前季度收入的乐观预测,显示出其新推出 一、AMD第三季度营收预期超越分析师平均预期 AMD在周二的声明中预计,第三季度营收将达到约67亿美元,这一数字超出了分析师此前平均预期的66.…...
如何提高计算机视觉技术在复杂环境和低光照条件下的物体识别准确率?
要在复杂环境和低光照条件下提高计算机视觉技术的物体识别准确率,可以采取以下几个方法: 数据增强:在训练集中添加各种复杂环境和低光照条件下的图片,通过增加数据的多样性,使算法能够更好地适应各种场景。 预处理&am…...
ubuntu cmake使用自己版本的qt
给一篇文章参考 https://blog.csdn.net/bank_dreamer/article/details/138678909 自己使用的范例 set(Qt5_DIR "/home/peak/Qt5.14.0/5.14.0/gcc_64/lib/cmake/Qt5")# 设置Qt5的安装目录 #set(CMAKE_PREFIX_PATH "/home/peak/Qt5.14.0")find_package(Qt5…...
Python基础知识笔记---保留字
保留字,也称关键字,是指被编程语言内部定义并保留使用的标识符。 一、保留字概览 二、保留字用途 1. False:表示布尔值假。 2. None:表示空值或无值。 3. True:表示布尔值真。 4. not:布尔逻辑操作符…...
Python面试整理-Web开发
在Python中,Web开发可以利用多种强大的框架和库来构建从简单的静态网页到复杂的动态Web应用。以下是几种流行的Python Web开发框架和相关技术的概述: 1. Flask Flask 是一个轻量级的Web应用框架,它非常灵活,适用于小型到中型项目,或作为构建微服务的基础。Flask的核心非常…...
民大食堂用餐小程序的设计
管理员账户功能包括:系统首页,个人中心,用户管理,商家管理,档口号管理,商家餐品管理,餐品种类管理,购物车管理,订单信息管理 微信端账号功能包括:系统首页&a…...
Linux系统编程(4):消息队列
Linux下的进程通信手段基本上是从Unix平台上的进程通信手段继承而来的。 而对Unix发展做出重大贡献的两大主力AT&T的贝尔实验室 以及 BSD(加州大学伯克利分校的伯克利软件发布中心), 他们在进程间通信方面的侧重点有所不同; 前…...
【初阶数据结构篇】单链表的实现(赋源码)
文章目录 单链表的实现代码位置概念与结构概念:结构: 链表的性质链表的分类单链表的实现单链表的创建和打印及销毁单链表的创建单链表的打印单链表的销毁 单链表的插入单链表头插单链表尾插单链表在指定位置之前插入数据单链表在指定位置之后插入数据 单…...
LeetCode 2844.生成特殊数字的最少操作(哈希表 + 贪心)
给你一个下标从 0 开始的字符串 num ,表示一个非负整数。 在一次操作中,您可以选择 num 的任意一位数字并将其删除。请注意,如果你删除 num 中的所有数字,则 num 变为 0。 返回最少需要多少次操作可以使 num 变成特殊数字。 如…...
昇思MindSpore 应用学习-基于 MindSpore 实现 BERT 对话情绪识别
基于 MindSpore 实现 BERT 对话情绪识别 模型简介 BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模…...
【初阶数据结构篇】顺序表和链表算法题
文章目录 顺序表算法题移除元素删除有序数组中的重复项合并两个有序数组 链表算法题移除链表元素反转链表链表的中间结点合并两个有序链表链表分割链表的回文结构 顺序表算法题 不熟悉顺序表的可以先了解一下 顺序表实现方法 移除元素 给你一个数组 nums 和一个值 val&#x…...
使用weex进行APP混合开发
Weex 是一个用于构建高性能原生应用的框架,它使用 Vue.js 的语法和组件模型,允许开发者使用 HTML、CSS 和 JavaScript 来编写应用,同时能够编译成原生应用。Weex 主要由阿里巴巴集团开发,并且已经被多个公司采用。 下面是使用 We…...
C++stl大根堆/小根堆的创建与记忆
priority_queue<int, vector<int>, greater<int>> heap; 这行代码在 C 中声明了一个优先队列 heap,其元素类型为 int,使用 vector<int> 作为其底层容器,并且指定了 greater<int> 作为比较函数对象。 这里的关…...
visual studio性能探测器使用案列
visual studio性能探测器使用案列 在visual studio中,我们可以使用自带的工具对项目进行性能探测,具体如下 1.选择性能探查器 Vs2022/Vs2019中打开方式: Vs2017打开方式: 注意最好将解决方案配置为:Release Debu…...
redis的代码开发
redis是什么? 前提:官网地址https://redis.io 1.Redis是一个开源的,key,value格式的,内存型数据结构存储系统;它可用作数据库、缓存和消息中间件。 value支持多种类型的数据结构如strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglo…...
嗷呜,就问你接不接?
...
避免过拟合,参数大模型强,正则让模型不要走偏
1、加入惩罚项L1【绝对值】 和L2【默认 平方】,降低噪音的影响,减少权重W的值 2、丢弃法 层与层之间加入噪音,只能在全连接层使用 无偏差加入噪音 p为丢弃的概率 x 当概率p是0 否则为除以(1-p) 丢弃概率p 一般为0.1 0.5 def drop_out(x…...
探灵直播2026最新官方正版免费下载 一键转存 永久更新 (看到速转存 资源随时走丢)
下载链接 本文将为您客观介绍《探灵直播》的幕后作者、核心玩法机制,并将其与同类型竞品进行简单的横向对比,带您全面了解这款作品的独特之处。 一、 幕后作者:专注于美少女题材的 qureate 《探灵直播》的开发商 qureate 是一家在日本游戏界…...
企业盈利密码,商业模式必读经典书籍推荐
很多人一提到“商业模式”,脑子里马上会想到诸如盈利、流量、融资、裂变、风口等一类的关键词。但真正问一句:“商业模式到底是什么?”往往又说不清。有人把商业模式理解成赚钱的方法;有人觉得是营销套路;还有人认为只…...
王力宏重仓比亚迪,行业震惊
王力宏最近以腾势汽车全球代言人的身份亮相发布会,现场直言:“后悔10年前没投资比亚迪,这次我要把握机会。” 当被问及是否用代言费买了比亚迪股票,他大方承认“这是真的”。他还补充道:“10年前我做过一档节目&#x…...
SketchBook Pro 中文版
🎨 绘画爱好者必看!SketchBook Pro 中文破解版,让你的创意自由飞翔!✨ 👋 各位CSDN的小伙伴们,大家好呀~ 今天给大家带来一款超级好用的数字绘画神器—— SketchBook Pro 中文破解版!🎨🎨🎨 如果你是喜欢画画的、搞设计的、画概念图的,或者平时需要在电脑/平…...
智慧养老平台|基于SprinBoot+vue的智慧养老平台系统(源码+数据库+文档)
智慧养老平台 目录 基于SprinBootvue的外贸平台系统 一、前言 二、系统设计 三、系统功能设计 前台 后台 管理员功能 老人功能 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂码…...
BabelDOC终极指南:三步解决PDF翻译格式错乱难题
BabelDOC终极指南:三步解决PDF翻译格式错乱难题 【免费下载链接】BabelDOC Yet Another Document Translator 项目地址: https://gitcode.com/GitHub_Trending/ba/BabelDOC 还在为PDF文档翻译后格式混乱而烦恼吗?BabelDOC作为专业的PDF文档翻译工…...
Lovable应用性能优化全链路(首屏加载≤300ms实测方案)
更多请点击: https://codechina.net 第一章:Lovable应用性能优化全链路概览 Lovable 是一款面向高并发、低延迟场景的现代 Web 应用框架,其性能优化需贯穿开发、构建、部署与运行时全生命周期。理解各环节的协同关系与瓶颈传导路径ÿ…...
从零到通:在华为eNSP模拟器上玩转Telnet+AAA,一篇搞定远程管理核心交换机
从零到通:在华为eNSP模拟器上玩转TelnetAAA,一篇搞定远程管理核心交换机 刚接触华为网络设备的朋友们,是否曾被密密麻麻的命令行界面吓到?其实只要掌握几个核心配置,就能像专业网管一样优雅地远程管理交换机。今天我们…...
【Appium 系列】第13节-混合测试执行器 — API + UI 的协同执行
对应代码:配套代码/test/core/hybrid_test_executor.py说明:本节讲解当一个测试用例需要同时使用接口测试和 UI 测试时,如何协调执行。这节讲什么有些测试用例,光靠接口测试或 UI 测试都不够。比如"验证用户注册后能登录&quo…...
从单摆到机械臂:拉格朗日方程在机器人控制中的三个实战应用(附MATLAB/Simulink模型)
从单摆到机械臂:拉格朗日方程在机器人控制中的三个实战应用(附MATLAB/Simulink模型) 在机器人控制领域,动力学建模是连接理论设计与实际应用的关键桥梁。拉格朗日方程作为一种基于能量的分析方法,能够优雅地处理复杂系…...
