XXL-MQ 消息生产发送,消息落盘过程源码解读

503 阅读3分钟

写在前面

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

提出问题

先思考两个通用MQ问题
1 生产者Producer 如何将消息发送至XXL-MQ消息中心的?中间源码
2 XXL-MQ消息中心如何接收,落盘接收到的消息

数据流程图

wecom-temp-bce7d02c32c9cd23f21ee4c4e3b8cced.png

流程总结

1 生产者Producer调用XxlMqProducer.produce()方法开始发送消息

2 进行消息基础校验,属性丰富等validMessage(mqMessage)

3 将消息存放在生产者内存队列newMessageQueue

4 后台线程clientFactoryThreadPool不断消费内存队列,xxlMqBroker.addMessages()方法准备向MQ中心发送消息

5 xxlMqBroker被xxlRpcReferenceBean启动时动态代理,此时进入xxlRpcReferenceBean的动态代理类方法中

6 xxlRpcReferenceBean组装消息发送请求参数xxlRpcRequest

7 生产者底层netty通信传输,将此次请求传输至XXL-MQ中心netty

8 XXL-MQ中心 netty收到通信请求,并解析请求参数xxlRpcRequest,索引定位Spring serviceBean method 即此次请求目标执行方法上

9 目标方法被执行即 XxlMqBrokerImpl.addMessages(list),将消息存放至XXl-MQ中心内存队列newMessageQueue

10 XXL_MQ 后台线程executorService不断消费内存队列newMessageQueue,并最终进行数据落盘,入库Mysql

源码过程Debug图解

 1 生产者Producer调用XxlMqProducer.produce()方法开始发送消息    

企业微信截图_ff1ee5bc-3295-4b09-a6ac-ecd3bbeb0980.png

  2 进行消息基础校验,属性丰富等validMessage(mqMessage)

wecom-temp-e5fb0e6ef59fd2457a65324912c9dc19.png wecom-temp-f37cf26d120b3c8655a6ea75b57badea.png

3 将消息存放在生产者内存队列newMessageQueue

企业微信截图_de0ff64c-1c4c-4359-9961-22b5fbf20c78.png

4 后台线程clientFactoryThreadPool不断消费内存队列,xxlMqBroker.addMessages()方法准备向MQ中心发送消息
XxlMqClientFactory

wecom-temp-ad3d95f7e15d4f54fc71d0edee58e1e7.png

企业微信截图_9f1a91bf-5837-4fce-b70e-6eaee8574dcb.png

5 xxlMqBroker被xxlRpcReferenceBean启动时动态代理,此时进入xxlRpcReferenceBean的动态代理类方法中

wecom-temp-f67b87250123e40ddde056786f138dae.png wecom-temp-4801114c03318c8310d45ca84bf6c483.png

6 xxlRpcReferenceBean组装消息发送请求参数xxlRpcRequest

企业微信截图_a97ae485-e913-4e25-baa4-c398f9e699ab.png

7 生产者底层netty通信传输,将此次请求传输至XXL-MQ中心netty

企业微信截图_6eb7b6f2-370a-41da-8248-e564321677aa.png wecom-temp-43ae758182d6bff6450c4a50911fec8c.png

8 XXL-MQ中心 netty收到通信请求,并解析请求参数xxlRpcRequest,索引定位Spring serviceBean method 即此次请求目标执行方法上

企业微信截图_55ad2951-339a-40be-9d97-05db3be54f33.png 企业微信截图_882578aa-7fd3-4eaf-aebd-3afe90e09773.png 企业微信截图_f8759175-83d4-454f-9d0a-bef24ff83bb2.png

9 目标方法被执行即 XxlMqBrokerImpl.addMessages(list),将消息存放至XXl-MQ中心内存队列newMessageQueue  

企业微信截图_21cb0383-2555-4746-abb0-984705b916c2.png

 10 XXL_MQ 后台线程executorService不断消费内存队列newMessageQueue,并最终进行数据落盘,入库Mysql 

企业微信截图_139766e3-cd45-4172-9443-92b8480f92a1.png

拓展

广播消息与普通消息发送的区别
    广播消息在发送时会查看当前消息分组Group有多少,例如有三个Group1,Group2,Group3,然后将当前消息的属性group设置成对应值,然后进行三次不同的发送
    如图       

企业微信截图_e9f6c17d-9ad2-43f4-a3ef-b2bd39a4ed3a.png

延迟消息与普通消息发送的区别
  首先在XXL-MQ的设计中,消息有一个属性effectTime(即表示消息的生效时间, new Date()立即执行, 否则在生效时间点之后开始执行)
  一般延迟消息应用于以下场景 ***支付**订单,10分钟后未支付则取消订单
  所以例如需要设置一个5分钟后的延迟消息,则将属性effectTime进行对应 +5分钟      

关于消息消费过程,靓仔们也可以看下我的另一篇文章记一次XXL-MQ消息消费失败的排查过程 企业微信截图_b34e3391-c380-4bf0-b3a3-95b5c88c37ea.png

写在最后

站在巨人的肩膀看世界,感谢xuxueli大佬的开源项目XXL开源社区

我是杨少,祝你幸福