XXL-MQ 消息消费,超时,重试 过程源码解读

写在前面

     作者一直想深入的去研究一款消息队列MQ,例如 延迟消费,广播消息,失败重试等机制.
 奈何市面上的MQ中间件太多了,如kafka,activeMQ,rocketMQ....所以也一直在纠结该以哪款为入手点,对新人友好?
 想起作者曾深入的研究了xuxueli大佬的分布式调度系统(XXL-JOB),然后进入XXL社区,刚好发现了的另一个开源项目,即分布式消息队列(XXL-MQ).       
   
   简而言之四个字,以小见大,懂得都懂
   
复制代码

提出问题

1 消费端是如何进行消息消费的,消费端与MQ中心的数据流程是怎么样的?
2 如何控制超时消费,重试消费?
复制代码

数据流程图

wecom-temp-152220669dea9d4aebb1a0c9eaedb490.png

流程总结

1 消费端程序启动时,初始化MQ连接配置Bean XxlMqSpringClientFactory
  该XxlMqSpringClientFactory类继承了Spring框架的拓展类ApplicationContextAware
  
2 进入ApplicationContextAware的setApplicationContext()方法,并开始初始化XxlMqClientFactory

3 扫描项目中实现MqConsumer接口的类,即扫描所有topic类,并将信息存放在内存
List<ConsumerThread>中

4 根据不同ConsumerThread 的topic 启动对应的后台轮询线程,即拉取MQ消息的线程ConsumerThread.execute()

5 进行到ConsumerThread 线程中,查看线程拉取MQ消息方法xxlMqlBroker.pullMessages()

6 xxlMqlBroker此时被XxlRpcReferenceBean动态代理掉了,因此进入XxlRpcReferenceBean动态代理类

7 组装远程调用参数XxlRpcRequest,并底层通过netty 向MQ中心发起通信

8 MQ netty收到此次通信请求,并解析参数XxlRpcRequest,索引定位到目标执行方法Spring serviceBean Method

9 反射执行目标方法XxlMqBrokerImpl.pullNewMessage(),获取到MQ中心的消息,并neety通信返回结果至消费端

10 消费端判断此次消息是否有超时限制,有则通过FutureTask.get()辅助工具类,限制超时
   无则直接通过反射底层执行topic消费方法即IMqConsumer.consume()
   
11 此次消费结束,消费端调用callbackMessage(msg)函数,将消费情况进行反馈,即为后续的失败重试机制做准备
复制代码

源码过程Debug图解

1 消费端程序启动时,初始化MQ连接配置Bean XxlMqSpringClientFactory
  该XxlMqSpringClientFactory类继承了Spring框架的拓展类ApplicationContextAware
复制代码

企业微信截图_bbb9b79e-b904-4d87-a6d7-ca3f100066bb.png 企业微信截图_850adcae-22dc-4007-86e5-4693ca5fbaf3.png

2 进入ApplicationContextAware的setApplicationContext()方法,并开始初始化XxlMqClientFactory
复制代码

企业微信截图_e2990c72-bd71-4c3f-8f72-3ce7ca20355f.png

3 扫描项目中实现MqConsumer接口的类,即扫描所有topic类,并将信息存放在内存 List<ConsumerThread>中  
复制代码

wecom-temp-4d20c4eee896970e958fe4280b3546e8.png

4 根据不同ConsumerThread 的topic 启动对应的后台轮询线程,即拉取MQ消息的线程ConsumerThread.execute()
复制代码

企业微信截图_c6cc82da-b4b9-4a44-8d6f-77b8be39cd47.png

5 进行到ConsumerThread 线程中,查看线程拉取MQ消息方法xxlMqlBroker.pullMessages()
复制代码

企业微信截图_a9c67504-d8bc-4d4a-a9d7-e5f02a2af6a9.png

6 xxlMqlBroker此时被XxlRpcReferenceBean动态代理掉了,因此进入XxlRpcReferenceBean动态代理类 
复制代码

企业微信截图_3f5bc9d6-bb8d-4071-9e7a-57dff392f29d.png wecom-temp-cc93d9ca8ebaaf43c64d63137d3ead46.png 企业微信截图_1caf7258-6c6a-4c09-9ed3-cf0c9a30d388.png

7 组装远程调用参数XxlRpcRequest,并底层通过netty 向MQ中心发起通信
复制代码

企业微信截图_b3081389-a755-465c-b836-c98f50df316d.png 企业微信截图_503370cf-510c-4b30-b37f-1af4613efd56.png

8 MQ netty收到此次通信请求,并解析参数XxlRpcRequest,索引定位到目标执行方法Spring serviceBean Method    
复制代码

wecom-temp-f6b775638d83d5c2020458717e7b4d98.png 企业微信截图_117c45b1-a6c1-4be1-a1e9-d6464b130229.png

9 反射执行目标方法XxlMqBrokerImpl.pullNewMessage(),获取到MQ中心的消息,并neety通信返回结果至消费端
得到查询的sql语句
SELECT *
FROM xxl_mq_message t
WHERE t.topic = 'topic_1'
AND t.group = 'DEFAULT'
AND t.status = 'NEW'
AND t.effectTime < NOW()
AND ((t.shardingId = 0
	AND MOD(t.id, 2) = 0)
OR (t.shardingId > 0
	AND MOD(t.shardingId, 2) = 0))
ORDER BY t.id ASC
LIMIT 100   
复制代码

wecom-temp-370bdd53e3981af2bc665d5c2223bfa5.png wecom-temp-00e2bc97a130b927c55c08cc5b161424.png

10 消费端判断此次消息是否有超时限制,有则通过FutureTask.get()辅助工具类,限制超时
   无则直接执行topic消费方法即IMqConsumer.consume()     
复制代码

企业微信截图_b0041da7-7771-47a5-8981-cdcd2b303f20.png
企业微信截图_6b5535f0-050c-4588-a81a-9d5f7024c457.png 企业微信截图_068a54d2-4c1e-4fac-9b20-fb7c1866a4af.png

11 此次消费结束,消费端调用callbackMessage(msg)函数,将消费情况进行反馈,即为后续的失败重试机制做准备    
复制代码

企业微信截图_5f7397bd-85fa-4fdb-9c0b-7911a4ae4086.png

写在最后

个人思考 如何去考虑消息的顺序性消费
复制代码

Guess you like

Origin juejin.im/post/7068534831914680351
Recommended