RabbitMq TTL+死信队列 延迟消息问题记录
延迟队列存储的对象是对应的延迟消息,所谓的延迟消息是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费
(资料图片)
利用RabbitMq
的TTL
和死信队列 来实现延时消费。
如果设置的是队列统一过期时间放到死信队列,没有什么问题。
如果是延时时间设置到每条消息上的。而不是给队列的。
实现方式为消息存活时间为动态用户页面可配置的。
这就导致了一个问题:
先用一条消息的存活时间是1天。后面又进了一条消息存活时间是1小时。
结果一小时到了,发现这条消息并没有被转发到消费延时过期消息的队列。
原因是尽管ttl是设给每条消息的。但是本质上,所有延时消息都还在一个队列里,对它过期时间的检测也是从头部开始的。
它不会检测每一条消息是否过期。而是顺序检测。
如果first in
的消息过期时间很长,会导致它阻塞后进的消息。
不仅无法实现真正的过期时间。还会导致,一个大的过期时间的先进的消息,会堆积一堆后进的过期时间短的消息。
问题解决
这个时候可以使用rabbitMq的一个插件:rabbitmq_delayed_message_exchange
一段时间以来,人们一直在寻找用RabbitMQ实现延迟消息的传递方法,到目前为止,公认的解决方案是混合使用TTL和DLX。而rabbitmq_delayed_message_exchange插件就是基于此来实现的,RabbitMQ延迟消息插件新增了一种新的交换器类型,消息通过这种交换器路由就可以实现延迟发送
插件安装
需要根据自己的rabbitMq选择对应的版本。我rabbitMq的版本是RabbitMQ 3.11.0
,对应的插件版本就是:3.11.1
基于Linux
--1、cd到rabbitmq默认安装位置cd /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.18/plugins--2、通过ftp工具将插件上传到此目录下--3、开启插件rabbitmq-plugins enable rabbitmq_delayed_message_exchange--4、重启MQ服务systemctl restart rabbitmq-server
基于Docker
--1、通过ftp工具将插件上传到Linux服务器的根目录下--2、拷贝到docker中rabbitmq插件目录下,rabbitmq_delayed_message_exchange-3.9.0.ez(下载包的全名)docker cp /rabbitmq_delayed_message_exchange-3.9.0.ez 容器ID:/plugins--3、进入容器docker exec -it 容器id /bin/bash--4、查看插件是否存在(确保2中的操作已经将插件拷贝过来了)cd pluginsls |grep delay--5、开启插件rabbitmq-plugins enable rabbitmq_delayed_message_exchange--6、退出容器exit--7、重启MQ服务docker restart 容器ID
安装成功
web界面新建交换机选择类型出现红框标注即表示成功
代码实现
1:springBoot配置
@Configurationpublic class DelayRabbitmqConfig { /** * 声明延迟队列 * @return */ @Bean public Queue delayQueue(){ return new Queue(QueueConstant.DelayQueue, true,false,false); } /** * 声明延迟自定义交换机类型 * @return */ @Bean public CustomExchange delayCustomExchange(){ HashMap args = new HashMap<>();// 设置 x-delayed-type 为 direct,当然也可以是 topic 等 发送消息时设置消息头 headers 的 x-delay 属性,即延迟时间,如果不设置消息将会立即投递 args.put("x-delayed-type","direct"); return new CustomExchange(ExchangeConstant.DelayCustomerExchange, "x-delayed-message",true,false,args); } /** * 绑定延迟交换机和队列 * @return */ @Bean public Binding delayQueueAndCustomExchange(){ return BindingBuilder.bind(delayQueue()) .to(delayCustomExchange()).with(RoutingKeyConstant.DelayCustomerRoutingKey).noargs(); }}
springMvc配置
引入依赖: xmlns:util="http://www.springframework.org/schema/util" http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd
代码实现
//消息发送final MessagePostProcessor messagePostProcessor = new MyMessagePostProcessor(Integer.valueOf(ttl.toString()));DisTimingPushDto disTimingPushDto = new DisTimingPushDto();disTimingPushDto.setOrderId(dispense.getOrderId());disTimingPushDto.setPushTime(disDispense.getPushTime());rabbitTemplate.convertAndSend(MsgQueueEnum.TIMING_PUSH.getExchangeName(), MsgQueueEnum.TIMING_PUSH.getQueueName(), disTimingPushDto, messagePostProcessor);//每条消息时间配置import org.springframework.amqp.AmqpException;import org.springframework.amqp.core.Message;import org.springframework.amqp.core.MessagePostProcessor;/** * 延迟消息处理器 Processor * @author king * @date 2022年12月28日 11:14 */public class MyMessagePostProcessor implements MessagePostProcessor { /** * 消息延迟时间,单位:毫秒 */ private final Integer TTL; public MyMessagePostProcessor(final Integer ttl) { this.TTL = ttl; } @Override public Message postProcessMessage(Message message) throws AmqpException { message.getMessageProperties().setDelay(TTL); return message; }}
标签: RabbitMQ
相关文章
RabbitMq TTL+死信队列 延迟消息问题记录
原因是尽管ttl是设给每条消息的。但是本质上,所有延时消息都还在一个队列里,对它过期时间的检测也是从头部开始的。
postek标签打印机售后电话_postek标签打印机官网 世界简讯
1、1 确认机器开机有运转声音,如没有运转声,将打印机耗材重新安装后,问题依旧,建议联系当地服务中心。2、2 如运转正常
闺蜜在沙滩拍照姿势_闺蜜在沙滩拍照姿势图
1、在休闲假期,我们经常会选择和闺蜜朋友一起出去玩,沙滩也是最受欢迎的场地之一。当然,外出游玩少不了拍照。那么和闺蜜去海
《我们的日子》傅莹的“破嘴”,从跑火车到挨巴掌,让多少人释然
《我们的日子》热播,李乃文和李小冉主演的这部剧,除了家长里短,就是鸡毛蒜皮,让人觉得很没有年代大剧的感觉。直到傅莹被开除后,因误会大
【独家焦点】安恒信息(688023.SH)业绩快报:2022年度净亏损2.52亿元
格隆汇2月27日丨安恒信息(688023 SH)发布2022年度业绩快报,实现营业总收入19 82亿元,同比增长8 87
【环球新视野】肝胆彩超能检查出什么疾病_肝胆彩超能检查出什么
1、这问题太泛泛了。2、大体说说可能的:肝囊肿、肝血管瘤、肝硬化、肝癌、胆囊结石、胆囊息肉、胆囊炎、胆囊癌等等。本文到此
辽国皇帝列表及简介_辽国开国皇帝是谁-每日时讯
欢迎观看本篇文章,小升来为大家解答以上问题。辽国皇帝列表及简介,辽国开国皇帝是谁很多人还不知道,现在让我们一起来看看吧!
《命运2》缚丝开发理念分享,将偶然BUG改成有趣技能
在《命运2》过往的版本中,无数的科幻迷们被吸引入坑,在这里我们曾经登上太空电梯直奔星云,也曾经深深凝视过木星的身影;甚至还在炽天使赛季
eui插件在战斗中怎么设置_eui插件官网
1、这个设置是匹配以前的你设置的eui插件内容,省去了重新设置的麻烦。2、对话框里输入 ec然后回车,出来eui的设
如何解决Windows10无法找到输出设备_win10找不到输出设备
1、如何解决Windows10找不到输出设备的问题?让我们来看看边肖。2、按[WinR]组合键打开操作,输入:serv
环球观点:保底售电如何“保底”?
保底售电是售电市场稳定运行的重要组成部分。随着我国电力市场改革的深入,亟需设计更完善的保底售电服务机制以保证电力交易平稳开展。贵州省
明星基金经理不能撂挑子一走了之_全球微速讯
证券时报记者余世鹏公募基金行业的“去明星化”在2023年春天开始了。多位管理规模上百亿的明星基金经理或离任或卸任产品。
保险金额跟保险费的区别-保险金额与保险费的区别 环球速看
1、投保金额和保险金额区别通俗讲就是(父子关系):1 投保金额是每年向保险公司缴纳的钱数目。2、2 保险金额是保险公司根据所购买保险产品的
观点:孕吐什么时候开始和结束_孕吐什么时候开始
1、孕吐主要是由于胚胎发育中期分泌绒毛膜促性腺激素,对机体产生一些影响,表现为消化系统的反应,称为孕吐。2、但是,每个人
由于没有安装音量控制程序以致无法显示音量控制_控制面板音量无法打开
1、Windows无法在任务栏上显示音量控制,因为没有安装音量控制程序。2、百度搜索下载sndvol3exe3、解压到C
无法办理房产抵押贷款的房屋类型有哪些?
不能办理抵押贷款的房屋类型有:1、小产权房;2、违章建筑;3、文物保护建筑;4、不能提供购房合同或购房协议的公房、不能提供央产房上市证明
Superdrug 推出拥有 300 个品牌的健康与美容市场_环球快看
Superdrug推出了拥有300个品牌的健康和美容市场。这家健康和美容零售商的新平台拥有一系列品牌,从UpC
英特尔中国区董事长:会与中国客户研究布局类ChatGPT算力模式
鞭牛士2月25日消息,英特尔全球高级副总裁、中国区董事长王锐表示,ChatGPT对英特尔中国也是好事情,下一步跟中国客户去共同研究如何去布局,