RocketMQ源码学习 (十三) 调度消息(延迟消息)服务端实现

1 回顾并发消费服务

在之前对消费者消费消息的篇章中我们知道当消息消费失败之后会返回RECONSUME_LATER,之后在消息结果处理中会执行消息回退逻辑没吊用sendMessageBack方法,在该方法里面有ConsumerSendMsgBackRequestHeader对象,该对象包含了delayLevel延迟级别,延迟级别由消息上下文控制,默认值是0,如果为0则延迟级别由broker控制,>0客户端控制延迟级别, ==-1则进入死信队列。设置延迟的原因前文也叙述过,此处不再赘述。不同的延迟级别对应的不同的延迟队列,不同的延迟队列的延迟的时间长度是不一样的,1s、2s、2小时等。根据这条消息去创建新的消息存储到延迟队列,延迟队列到时间之后再去创建新的消息存储到"%RETRY_TOPIC%+consumerGroup"的主题中去,每重试一次对应的该主题就会新建一条消息,该消息有自己的msgId,因此需要保存最原始的msgId和原始消息主题,最大重试次数为16。
接下来就看一下到底如何处理延迟消息的。

2 调度消息(延迟消息)服务端实现

消费者将延迟消息封装成RequestCode为CONSUMER_SEND_MESSAGE_BACK的RemoteCommand对象发送给broker,在briker中最终调用SendMessageProcessor方法,该方法内部调用处理消息回退的逻辑,如下:
在这里插入图片描述

在调用存储模块的asyncPutMessage方法存储消息时,该方法内部主要流程如下:

在这里插入图片描述

3 调度消息服务

调度消息服务在DefaultMessageStore里面,delayLevelTable存的是每个延迟级别下需要延迟的时间长度,默认支持18个级别;offsetTable存的是每个“SCHEDULE_TOPIC_XXXX”主题下自己的queue的消费进度(每五秒持久化一次),SCHEDULE_TOPIC_XXXX主题的消息由broker自己去消费

当检查SelectMappedBufferResult内具有有效数据时,会走下图的逻辑开始循环;
计算的差值(系统当前时间-消息交付时间)<=0时,需要将消息交付出去,否则继续延迟。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值