在之前的文章中,已经把 Broker、Producer 和 Conusmer 的部分源码和核心的机制介绍的差不多了,但是其实 RocketMQ 中还有一个比较关键但是我们平时很容易忽略的组件——NameServer。
在日常的使用中,我们接触的最多的还是 Producer 和 Consumer,而 NameServer 没有直接跟我们有交互。就像 Kafka 集群背后用于其集群元数据管理的 Zookeeper 集群一样,NameServer 也在背后支撑着 RocketMQ 正常工作。
你给翻译翻译,什么叫 NameServerNameServer 你可以简单的把它理解成注册中心。
Broker 启动的时候会将自己注册到 NameServer 中,注册的同时还会将 Broker 的 IP 地址、端口相关的数据,以及保存在 Broker 中的 RocketMQ 集群路由的数据一并跟随心跳发送到 NameServer。这里的路由信息是指 Topic 下的 MessageQueue 分别都在哪台 Broker 上。
而 Producer 则会从 NameServer 中获取元数据,从而将 Message 发到对应的 Broker 中去。
相应的,Consumer 也需要从 NameServer 中获取数据。平常我们配置消费者,里面重要的信息主要就两个,分别是你要消费的 Topic 和当前的 Consumer Group。根据配置,Consumer 会去 NameServer 获取对应的 Topic 都有哪些 Broker,其真实的 IP 地址和端口是多少,拿到了这个之后就可以开始进行消息消费了。
注册 Broker 都做了什么这里我们先通过注册 Broker 的源码来预热一下,为后面阅读整个部分的源码做准备,直接上代码。
首先这里做了一个对 Broker 版本的区分,不同的版本采用不同的处理方式,鉴于官网现在最新的版本都已经到了 4.9.0 了,就暂时先不考虑低版本的情况了,后面有时间再讨论。
只有向上面那种几行的代码会给大家贴出来,其余的代码我会尽量用流程图代替
校验 Body 的完整性首先是校验 Broker 传过来的数据的完整性。很简单的一个判断,将 Broker 传过来的 Body 用 CRC32算法 加密之后,和请求中 Header 中所带的由 Broker 加密的值进行对比,不同的话就说明数据的完整性出了问题,接下来需要中断注册流程。
解析Body这里分成两种情况:
Body为空
Body不为空
如果 Body 为空,则会将当前要注册的 Broker 的 DataVersion 给重置;
而 **Body 不为空 **则会进行对 Body 进行解析,主要是从中解析出 DataVersion ,代表 Broker 中的数据版本。其次解析出这个 Broker 中存储的所有 Topic 及其相关的配置。
执行注册逻辑这里就是注册的核心逻辑了,这里为了更加容易理解,我们来分情况讨论,就不把两种情况揉在一起了。
首次注册
非首次注册
维护集群中 Broker 的 Name在整个操作开始之前,会先给 RouteInfoManager 加一把锁,这个 RouteInfoManager 里面就是 NameServer 存储数据的地方。这个锁是个读写锁,使用的是 Java 中的 ReentrantReadWriteLock。
这里的 BrokerName 是在 RocketMQ 配置文件中配置的变量。就是用于标识一个 Broker 的名字,但我们知道 Broker 是有主从架构的,并且 RocketMQ 4.5 之后推出的 Dleger 可以实现一主多从,换句话说,一个 Broker Name 可能会对应多个 Broker 实例。
在 MQ 看来,Broker 是多实例部署的;而在 Producer 或者 Consumer 来看,Broker就只有一个。所以,这个步骤内所维护的就是在当前集群中,有多少个这样的 Broker Name。
维护 Broker 的数据然后,RocketMQ 会在 brokerAddrTable 中维护每个 Broker 的核心数据,包含:
Broker 所处的集群
Broker 的名字(上面刚刚讨论过)