前言
前面两篇文章中分享了Producer和Consumer的期待过程,在这篇文章中将会分享NameServer的源码解析。
NameServer的定位
在RocketMQ中,存在四个角色:Producer、Consumer、Broker、NameServer。前三个都好理解,和消息的产生、中转、消费息息相关。而NameServer是以一个协调者的角色出现在RocketMQ中的。可以将NamerServer理解成一个管家,它存储着一些元信息,最重要的是消息的一些路由信息,不论是Producer发送消息的时候还是Consumer消费消息的时候,都需要知道这个Topic在哪个Broker中,NameServer的任务和意义就在于此。
NameServer在设计时将其设计成了一个无状态的服务器,即NameServer可以集群部署,但是NameServer节点之间不存在任何的信息交互,为了保证NameServer服务器之间的信息同步就要求Broker向每一个NameServer实例建立长连接,并且在Broker状态和信息更新时同步到所有的NameServer。一般来说,NameServer的负载很小,对于中等规模的RocketMQ集群而言,只需要两台NameServer实例热备即可,一般不会存在上下线NameServer实例的过程,
NameServer的启动分析
NameServer的启动过程中最重要的是创建了一个NamesrvController,并开启了这个controller。
构造Controller的过程是解析配置文件的过程,在start函数中,会调用到controller的init方法,在该方法中将会执行加载解析后的配置、开启Netty服务器、初始化线程池,并注册Processor,并注册一个定时任务,该任务会定期的扫描Broker,发现其中无效的Broker并清理。
在init完毕后,调用controller的start函数,开启网络服务,并开启文件监听服务,文件监听主要是动态的加载配置文件。
NameServer功能分析
在上述的启动分析中我们可以很清楚的看到,启动过程就是初始化配置,并开启Netty服务器的过程,但是我们注意到,它的主要功能处理器是通过registerProcessor函数来注册是,即NameServer的主要功能是由Processor来体现的。
从代码可以看出,集群测试有一个独立的测试Processor。我们先分析默认的Processor。
从图中可以清楚的看到Processor的任务,包括上下线Broker,获取Topic路由消息,获取Broker集群消息。
上线Broker
当一个Broker实例被启动时,需要和NameServer建立长链接,此时会触发Broker的上线操作,详细分析见Broker篇。在NameServer中,会从Broker的上线请求中提取出其中的Topic配置信息,并通过RouterInfoManager注册Broker。
在Broker上线这个场景中存在几个情况:1、一个全新的Broker实例加入到Broker集群中;2、Broker的slaver升级成为master。对于第二种,NameServer的记录中必然存在其实例的信息。
在此需要说明的每一个Broker存在一下属性:BrokerName(Broker自己的名字)、cluster(broker所属集群的名字),BrokerAddr(Broker的地址)。相应的在NameServer中存在一下的几个数据结构:ClusterTable(是一个关于Cluster的map,key为clusterName,value是一个Set,记录着集群下的所有Broker)、BrokerAddrTable(存储所有Broker地址的一个map,key是brokerName,value是BrokerData,BrokerData记录着一个Broker的元信息)。根据RocketMQ官方的文档,BrokerName为一组Broker共享,在着一组Broker中存在一个master节点(BrokerId为0)和一系列的slaver节点(BrokerId非0),这些Broker都共享一个BrokerName。
NameServer的Broker上线操作包括一下几个步骤
1、将Broker地址端口信息添加到Broker列表中,
2、随后判断Broker中的Topic配置有没有变更,若出现了变更则更新QueueData。
3、将Broker信息添加到LiveTable中。
4、返回添加结果
Broker上线最重要的过程是更新Topic的路由表。此时需要原先的QueueData清除,再添加新的,在这个过程中更新了topicQueueTable。
获取Topic路由信息
获取路由信息的入口在RouterInfoManager的pickupTopicRouteData()函数。
在RouterInfoManager中用到了Topic相关的核心数据结构:topicQueueTable。在Broker上线时更新的topicQueueTable数据在此处被用上。具体操作如图。
从topicQueueTable拿到存储Topic的Broker列表,并填充BrokerName,最后依据BrokerName获取得到每一个Broker小组的BrokerData。