1、问题
rocketMQ开源版只支持18种延时队列,期望扩展延迟等级,或者自定义延迟时间。
为什么她只支持18种呢?我们带着问题去看源码。
2、分析过程
分析过程较长,可以直接跳到后面看结论。
2.1、先从client端入手
Message msg = new Message(topic, tag, msgKey, msgBody.getBytes(RemotingHelper.DEFAULT_CHARSET));
// 组装消息时候需要设置延迟level,那么就从源码中的这个对象入手
msg.setDelayTimeLevel(level.getLevel());
defaultMQProducer.send(msg, sendTimeout);
2.2、查看rocketMQ源码使用delay level方式
a.在CommitLog类中找到了使用level方式:
b.在ScheduleMessageService类中找到了start方法,里面进行了初始化定时器:
c.在ScheduleMessageService.parseDelayLevel()中对level map进行了初始化
d.继续查看MessageStoreConfig类初始化和使用情况。
e.通过查看MessageStoreConfig的初始化过程,反查到了BrokerStartup.start()方法,也就是在broker启动加载了这个config(这点早该想到。。。)
通过反查代码,大致延迟队列处理流程应该是这样:message提交后会替换topic和queueId,每个queueId都有自己定时任务扫描队列,满足条件的放入commitLog中去消费。这样的好处是预设置了18种队列,代码实现方便,不用对消息进行排序操作。
既然知道原理和代码,那么修改方式也就十分简单了。
3、结论
在broken的配置文件中加入一行配置重启即可:
messageDelayLevel=1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 6h 12h
最好的方式是在后面追加,不要改前面18种。
后续:网上也找到一种实现任意延迟时间的方案(链接),方案实现较复杂,就算方案实现,收益也不高。添加部分延迟时间已满足需求。