开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第4天,点击查看活动详情
前言
通过上一篇文章「日拱一卒」带你探索RocketMQ消息发送(三),我们主要学了 RocketMQ 发送消息的 Demo、简要了解了 DefaultMQProducer 的属性和方法以及在源码的基础上分析了 RocketMQ 生产者的启动流程。今天,我们来承接上一篇文章,来开始学习下 RocketMQ 消息发送的基本流程吧!
消息发送流程概览
当 RocketMQ 的生产者对象 DefaultMQProducer 成功初始化完成后,会调用 send() 方法进行消息的发送。由于在实际项目中,我们通常会关注消息是否发送成功,因此,同步发送的方式是应用得比较多的。我们本篇文章,还是着眼于同步发送方法来研究原理。
对于单个消息的发送,主要有两个同步发送的方法:
-
发送消息
-
发送消息时,带上超时时间
它们底层调用的方法都是 defaultMQProducerImpl 类的 send 方法。接下来,我们以第一个发送消息的方法为例,来一起探索消息发送的流程吧!
验证消息长度是否合理
在消息发送之前,首先要校验一把消息的大小是否超出了限制或者不合法:
- Message 对象的 body 属性 byte[] 数组若为null,抛出异常
- Message 对象的 body 属性 byte[] 数组的长度若为0,抛出异常
- Message 对象的 body 属性 byte[] 数组的长度若大于 102410244 = 4M,抛出异常
查找主题
校验完消息后,开始对 Message 的 Topic 属性进行查询,只有查询到了 Topic 的路由信息,生产者才知道消息应该发送到哪个 Broker 节点上:
-
如果生产者的 topicPublishInfoTable (ConcurrentHashMap)中,缓存了 Topic 对应的路由信息 TopicPublishInfo,并且 TopicPublishInfo 中包含消息队列,则返回该路由信息。
-
如果缓存了 TopicPublishInfo,但是没有路由信息,也没有消息队列,则向 NameServer 查询该 Topic 的路由信息,并更新到 TopicPublishInfo 中
-
如果没有缓存,或者没有包含消息队列,则向 NameServer 查询该 Topic 的路由信息
-
如果最终未查询到路由信息,则返回报错
TopicPublishInfo 具体长啥样,我们来看一下:
- boolean orderTopic :是否是顺序消息
- boolean haveTopicRouterInfo: 是否有 Topic 路由信息
- List messageQueueList :该 Topic 的消息队列
- ThreadLocalIndex sendWhichQueue :每选择一次消息队列,该值会自增1
- TopicRouteData 中的 queueDatas:Topic 队列元数据
- TopicRouteData 中的 brokerDatas:Topic 分布的Broker元数据
- TopicRouteData 中的 filterServerTable:Broker 上过滤服务器的地址列表
小结
今天我们暂时了解了消息发送流程概览,看了下查找主题的代码,明天将会有更详细的解析,大家多多关注与支持!