注册中心namesrv
概述
在一个分布式服务系统里面注册中心是不可或缺的,因为它维护这服务的状态,防止分布式系统出现单点故障,提供高可用。
假使不使用注册中心,服务发现,那么就需要在客户端配置每个服务端的信息,那么在服务端横向扩容的时候就显得很生硬,服务发现功能主要是为了让服务自动注册,让客户端能够自动感知到服务端的状态信息,从而使用一定的策略权衡调用服务。
笔者源码版本4.8
rocketmq注册中心
网上普遍存在如下两个架构图:
不同于其他的注册中心:
rocketmq的namesrv之间是互不通信的,并且是不分M-S的,每台namesrv上面都维护着各自的broker信息,broker在发送心跳的时候会往所有的namesrv发送,因为互不通信,所以namesrv上的的数据可能会不一致,但是牺牲了CAP中的C(一致性),所以他的namesrv一定是高可用的,那么问题来了:
如果某个namesrv上存错误的信息怎么办呢?
producer从namesrv上面拿到路由信息之后,还会进行负载,根据具体broker情况选择发送。
namesrv启动
namesrv流程比较简单,我们快速分析:
直接来到org.apache.rocketmq.namesrv.NamesrvStartup#createNamesrvController方法,主要new了两个配置类:
MixAll.properties2Object这个方法的作用就是将配置文件转成对象:
接下来的流程还是读取配置文件,配置日志配置:
接着就来到代码 org.apache.rocketmq.namesrv.NamesrvStartup#start :
如下调用了141行 init方法:
在这个初始化里面:
new了一个netty service端
建了个线程池
然后将processer注册到remoting里面,主要关注这个方法:
可以看懂啊这里默认注册的事DefaultRequestProcessor这个类:
这个类我们在下面的发送心跳,拿路由信息的时候会讲到。
回到刚刚的init方法里面:
这里启动了两个定时任务:
- 每10s扫描不活跃的broker,有兴趣的读者可以进入到方法里看看具体逻辑—>遍历所有broker,最后一次心跳时间超过2分钟,就remove掉
- 每10分钟打印配置信息,configTable里面信息
接下来初始化了FileWatchService服务,该服务用于监听Ssl配置文件变化,这里不是我们主要分析的地方,只要知道他大概干什么就可以了
回到org.apache.rocketmq.namesrv.NamesrvStartup#start方法:
注册了一个关闭的钩子,主要是关闭一些netty连接,关闭线程池
我们接着跟进:
这里主要做两事:
启动remoting模块
启动ssl文件监控服务
我们先分析启动remoting:
来到org.apache.rocketmq.remoting.netty.NettyRemotingServer#start 这个方法:
启动了remoting的netty服务端:
主要关注一下端口号是9876:
至此,namesrv就已经启动完成。
broker发送心跳
在broker启动的时候,org.apache.rocketmq.broker.BrokerController#start方法里面启动了一个定时任务,用来注册自身到namesrv上面:
每30s执行一次:
直接来到org.apache.rocketmq.broker.out.BrokerOuterAPI#registerBrokerAll方法,:
如下是调用栈:
这里遍历了namesrv地址,然后对每个地址调用registerBroker方法,来注册broker,然后放到一个线程里面执行;
继续跟进:
因为是调用remoting模块,所以一定会构建一个request,而我们只要知道该请求的code是多少就可以了:
code=103
接着就来到namesrv里面的DefaultRequestProcessor类了:
直接来到org.apache.rocketmq.namesrv.processor.DefaultRequestProcessor#processRequest方法:
找到code为103的 REGISTER_BROKER:
这里我这边是4.8版本,所以走上面的逻辑:
接着会调用org.apache.rocketmq.namesrv.routeinfo.RouteInfoManager#registerBroker方法:
接着跟进:
来到RouteInfoManager路由管理类:
我们先了解一下这个类中的几个集合,都是存放什么的:
- topicQueueTable 存放topic信息
- brokerAddrTable 存放broker地址
- clusterAddrTable 存放集群信息
- brokerLiveTable 存活的broker信息
以及一个lock 读写锁:
接着上面流程最终会构建BrokerLiveInfo信息,设置到brokerLiveTable里面:主要注意这里讲当前时间作为心跳时间戳设置进去
这里就可以对上上面的,每10s中查看集合中心跳时间超过两分钟的会剔除掉。
至此broker注册,发送心跳就已经分析完毕。
路由发现
在之前生产者发送消息的时候,会去进行路由发现:
如果topic是空的,或者里面的queue是空的,就会去调用namesrv去获取topic信息:
接着会调用org.apache.rocketmq.client.impl.MQClientAPIImpl#getTopicRouteInfoFromNameServer(java.lang.String, long, boolean)进行路由发现:
然后就来到了,该方法:
这里面逻辑其实很朴实无华:
从topicQueueTable里面拿到queue,然后将queueDataList设置到topic信息里面返回即可:
总结
namesrv主要有逻辑:
- namesrv会定时清除过期broker
- namesrv接受到broker心跳,更新broker时间
- namesrv里多个获取信息的方法,主要代表为GET_ROUTEINFO_BY_TOPIC