NameServer是整个消息队列中的状态服务器,集群的各个组件通过它来了解全局的信息。同时,各个角色的机器都要定期向NameServer上报自己的状态,超时不上报的话,NameServer会认为某个机器出故障不可用了,其他的组件会把这个机器从可用列表里移除。
NamServer可以部署多个,相互之间独立,其他角色同时向多个NameServer机器上报状态信息,从而达到热备份的目的。NameServer本身是无状态的,也就是说NameServer中的Broker、Topic等状态信息不会持久存储,都是由各个角色定时上报并存储到内存中的(NameServer支持配置参数的持久化,一般用不到)。
在org.apache.rocketmq.namesrv.routeinfo的RouteInfoManager类中,有五个变量,集群的状态就保存在这五个变量中。
private final HashMap
topicQueueTable 这个结构的Key是Topic的名称,它存储了所有Topic的属性信息。Value是个QueueData队列,队里的长度等于这个Topic数据存储的Master Broker的个数,QueueData里存储着Broker的名称、读写queue的数量、同步标识等。
·private final HashMap
以BrokerName为索引,相同名称的Broker可能存在多台机器,一个Master和多个Slave。这个结构存储着一个BrokerName对应的属性信息,包括所属的Cluster名称,一个Master Broker和多个Slave Broker的地址信息。
·private final HashMap
存储的是集群中Cluster的信息,结果很简单,就是一个Cluster名称对应一个由BrokerName组成的集合。
·private final HashMap
这个结构和BrokerAddrTable有关系,但是内容完全不同,这个结构的Key是BrokerAddr,也就是对应着一台机器,BrokerAddrTable中的Key是BrokerName,多个机器的BrokerName可以相同。BrokerLiveTable存储的内容是这台Broker机器的实时状态,包括上次更新状态的时间戳,NameServer会定期检查这个时间戳,超时没有更新就认为这个Broker无效了,将其从Broker列表里清除。
·private final HashMap
Filter Server是过滤服务器,是RocketMQ的一种服务端过滤方式,一个Broker可以有一个或多个Filter Server。这个结构的Key是Broker的地址,Value是和这个Broker关联的多个Filter Server的地址。
从上面这五个变量的定义,可以清楚地看出各个组件的状态是如何存储的,NameServer的主要工作就是维护这五个变量中存储的信息。
本节基于源码分析NameServer如何维护各个Broker的实时状态,如何根据Broker的情况更新各种集群的属性数据。因为其他角色会主动向NameServer上报状态,所以NameServer的主要逻辑在DefaultRequest-Processor类中,根据上报消息里的请求码做相应的处理,更新存储的对应信息。此外,连接断开的事件也会触发状态更新,具体逻辑在org.apache.rocketmq.namesrv.routeinfo的BrokerHousekeepingService类中,如代码清单4-1所示。
代码清单4-1 Channel断开触发的回调函数
@Override
public void onChannelClose(String remoteAddr, Channel channel) {
this.namesrvController.getRouteInfoManager().onChannelDestroy (remoteAddr, channel);
}
@Override
public void onChannelException(String remoteAddr, Channel channel) {
this.namesrvController.getRouteInfoManager().onChannelDestroy (remoteAddr, channel);
}
@Override
public void onChannelIdle(String remoteAddr, Channel channel) {
this.namesrvController.getRouteInfoManager().onChannelDestroy (remoteAddr, channel);
}
当NameServer和Broker的长连接断掉以后,onChannelDestroy函数会被调用,把这个Broker的信息清理出去。NameServer还有定时检查时间戳的逻辑,Broker向NameServer发送的心跳会更新时间戳,当NameServer检查到时间戳长时间没有更新后,便会触发清理逻辑,如代码清单4-2所示。
代码清单4-2 定时Check Broker的状态
this.scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
NamesrvController.this.routeInfoManager.scanNotActiveBroker();
}
}, 5, 10, TimeUnit.SECONDS);
从代码可以看出是每10秒检查一次,时间戳超过2分钟则认为Broker已失效。