RabbitMQ延迟消息的延迟极限是多少?
之前在写Spring Cloud Stream专题内容的时候,特地介绍了一下如何使用RabbitMQ的延迟消息来实现定时任务。最近正好因为开发碰到了使用过程中发现,延迟消息没有效果,消息直接就被消费了的情况。因此就继续深入研究了一下问题原因,在此记录下来,给碰到类似问题的童鞋们参考。
问题定位
因为不是所有的消息都出现了没有延迟消息效果的因素,通过有问题的消息特征,大致猜测可能是延迟时间过长导致了消息延迟失败。为了验证这个原因,先拿之前文章中的例子,来测试一下延迟时间是否与问题直接相关。
对之前的延迟消息使用样例(文末的Git仓库中可以获取完整代码)接口做一下微改,增加了一个请求参数delay
来控制延迟时间:
@GetMapping("/sendMessage")
public String messageWithMQ(@RequestParam String message, @RequestParam Long delay) {
log.info("Send: " + message);
testTopic.output().send(MessageBuilder.withPayload(message).setHeader("x-delay", delay).build());
return "ok";
}
然后尝试发起了两个请求:
请求1:延迟5000毫秒。消息发送到MQ之后确实延迟了5秒之后才得到了消费,没有任何问题。
curl localhost:8080/sendMessage?message=hello&delay=5000
请求2:延迟1年(31536000000毫秒)。消息发送到MQ之后马上就被消费者消费了,完全没有延迟效果。
curl localhost:8080/sendMessage?message=hello&delay=31536000000
问题小结
在明确了问题原因之后,需要对该功能的时候做一些明确的限定(延迟时间的极限),以避免再次出现类似的问题。深入探索下去,这里的失败主要与消息的过期时间(TTL)有直接的关系。在RabbitMQ中,消息的过期时间必须是非负 32 位整数,即:0 <= n <= 2^32-1,以毫秒为单位。 其中,2^32-1 = 4294967295。
这里我们可以尝试下面两个请求,分别设置延迟时间为4294967295何4294967296:
curl localhost:8080/sendMessage?message=hello&delay=4294967295
curl localhost:8080/sendMessage?message=hello&delay=4294967296
可以发现,当延迟时间为4294967295毫秒的时候,延迟消息工作正常;当延迟时间为4294967296毫秒的时候,消息被直接消费,没有延迟效果。
所以,我们在使用RabbitMQ的延迟消息功能时候,必须注意它的延迟极限是4294967295毫秒。如果你的业务需求会超过这个临界值,就必须避开这个坑,采用其他方法来实现需要延迟或者定时执行的任务了。
代码示例
本文示例读者可以通过查看下面仓库的中的stream-delayed-message项目:
- Github: https://github.com/dyc87112/SpringCloud-Learning/tree/master/4-Finchley
- Gitee: https://gitee.com/didispace/SpringCloud-Learning/tree/master/4-Finchley
如果您对这些感兴趣,欢迎star、follow、收藏、转发给予支持!
欢迎关注我的公众号:程序猿DD,获得独家整理的学习资源和日常干货推送。如果您对我的专题内容感兴趣,也可以关注我的博客:didispace.com

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
-
上一篇
分布式Redis深度历险-Cluster
本文为分布式Redis深度历险系列的第三篇,主要内容为Redis的Cluster,也就是Redis集群功能。 Redis集群是Redis官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来进行数据共享。 集群基础实现 一个集群由多个Redis节点组成,不同的节点通过CLUSTER MEET命令进行连接: CLUSTER MEET <ip> <port> 收到命令的节点会与命令中指定的目标节点进行握手,握手成功后目标节点会加入到集群中,看个例子,图片来自于Redis的设计与实现: 槽分配 一个集群的所有数据被分为16384个槽,可以通过CLUSTER ADDSLOTS命令将槽指派给对应的节点。当所有的槽都有节点负责时,集群处于上线状态,否则处于下线状态不对外提供服务。 clusterNode的位数组slots代表一个节点负责的槽信息。 struct clusterNode { unsigned char slots[16384/8]; /* slots handled by this node */ int numslots; ...
-
下一篇
etcd实现故障时主备秒级切换高可用架构
什么是Etcd? etcd是一个强大的一致性的分布式键值存储,它提供了一种可靠的方式来存储需要由分布式系统或机器群访问的数据。它优雅地处理网络分区期间的领导者选举,并且可以容忍机器故障,即使在领导者节点中也是如此。从简单的Web应用程序到Kubernetes,任何复杂的应用程序都可以读取数据并将数据写入etcd。这是官方对Etcd的描述,基于这些特性,Etcd常用于分布式配置、分布式锁、分布式服务协调者以及分布式注册。从功能上来说和zookeeper是一类项目,但是相比而言etcd更现代,etcd使用go语言开发,编译后生成了系统可执行的二进制产物,跨平台性更好,更易维护。etcd直接提供http的接口,非常方便各大语言封装自己的client sdk,在易用性方面也更好一点。下面也主要使用java的客户端jetcd,解决主备服务的协调问题。 etcd项目地址:https://github.com/etcd-io/etcd etcd官网:https://etcd.io jetcd地址:https://github.com/etcd-io/jetcd 主备服务场景描述 很多时候为了服务的高...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS6,CentOS7官方镜像安装Oracle11G
- Dcoker安装(在线仓库),最新的服务器搭配容器使用
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- CentOS关闭SELinux安全模块