这里是weihubeats,觉得文章不错可以关注公众号小奏技术,文章首发。拒绝营销号,拒绝标题党
源码版本
- rocketmq:release-5.1.0
背景
继上一章我们分析了client端Nameserver地址更新的源码实现方式
现在我们继续研究client是如何创建更新topic并与broker、nameserver交互的
探索
这里我们源码探索的入口并不打算先从rocketmq源码包开始,因为创建topic的入口更多的是在rocketmq-dashboard,所以我们从rocketmq-dashboard,rocketmq-dashboard的版本使用最新的master,反正rocketmq-dashboard也没怎么维护了,所以倒是无所谓
入口
我们直接全局搜索topicCreate
会发现很容易找到这个controller:TopicController
然后入口也很明显就是topicCreateOrUpdateRequest这个方法
我们进入到topicService中的createOrUpdate方法看看
比较核心的两行代码我们可以注意一下
ClusterInfo clusterInfo = mqAdminExt.examineBrokerClusterInfo();
这里需要获取的是所有master的broker,因为只有master的 broker才是可写的
实际上不通过上面的方式获取,我们还可以通过如下代码获取
Set<String> masterSet = CommandUtil.fetchMasterAddrByClusterName(mqAdmin, mqCluster.getName());
毕竟有提供直接的工具类帮我们获取,我们为什么不用呢
这里是通过集群mqAdminExt去获取集群信息,实际是通过netty远程从nameserver获取的,我们可以简单看看这块通信代码
public static final int GET_BROKER_CLUSTER_INFO = 106;
我们通过code去找到server的业务处理器
获取broker集群的代码也很简单
这里仅仅是拿到所有master的broker地址,还没有正真开始创建topic
创建topic的核心方法是
mqAdminExt.createAndUpdateTopicConfig
需要注意的是这里的创建方式是for循环去所有主master broker创建
所以我们指定一个topic多少个readQueueNums和writeQueueNums就会在所有broker上建立相同数量的queue
所以像网上有些图比如:
这种在正常没有broker扩容的情况下是不对的,因为所有的broker上面的queue应该是相同数量的
客户端我们这里分析完了,接下来我们还是要去broker上面的源码去寻找我们需要真相。
要找到broker相关的请求处理器也很简单,我们看看createTopic发送的RequestCode是多少,就可以了
可以看到是
RequestCode.UPDATE_AND_CREATE_TOPIC
顺带提一句的是实际rocketmq-dashboard中使用的这些方法其实也是依赖了rocketmq中的一些模块的sdk比如
rocketmq-clinetrocketmq-tools
broker
我们通过寻找RequestCode的使用
就能找到broker的处理逻辑
AdminBrokerProcessor:updateAndCreateTopic(ChannelHandlerContext ctx, RemotingCommand request)
这段代码还是挺长的,我们挑重点分析
- 方法添加了
synchronized,防止并发冲突
final CreateTopicRequestHeader requestHeader =
(CreateTopicRequestHeader) request.decodeCommandCustomHeader(CreateTopicRequestHeader.class);
方法decodeCommandCustomHeader就是将客户端的请求参数转换到
CreateTopicRequestHeader对象中具体的转换,实际在编解码的时候所有属性都已经写入到extFields属性了,我们可以简单看看
3.
validateTopic去校验topic的合法性
这里的合法性校验很简单,我们看看代码就知道了
- 校验是否为更新系统的topic
if (brokerController.getBrokerConfig().isValidateSystemTopicWhenUpdateTopic()) {
if (TopicValidator.isSystemTopic(topic)) {
response.setCode(ResponseCode.SYSTEM_ERROR);
response.setRemark("The topic[" + topic + "] is conflict with system topic.");
return response;
}
}
- 将
CreateTopicRequestHeader requestHeader转换为TopicConfig
- 更新topic信息写入到broker
this.brokerController.getTopicConfigManager().updateTopicConfig(topicConfig);
topic相关的元数据信息存储默认在TopicConfigManager配置
可以看到默认是在user.home下
这里我们也可以简单看看实际的元数据存储是什么样子的
- 推送
brokertopic相关信息到nameserver
this.brokerController.registerIncrementBrokerData(topicConfig, this.brokerController.getTopicConfigManager().getDataVersion());
这里我们直接进入到最里面的通信模块,看几个核心的点,就是broker通过获取了nameServerAddressList然后循环去更新topic信息
总结
至此我们就分析完了topic创建、更新流程,我们总结一下
- client循环向集群中的所有master
broker注册topic信息 broker接受到创建或更新topic信息后本地创建topic然后写入本地文件中,同时会更新broker的内存topic信息,然后向所有nameserver更新topic信息
可以看到整体逻辑还是很清晰的
本文正在参加「金石计划」