NameServer作为RocketMQ的注册中心,主要存储了哪些信息,如何存储,信息有变更时如何通知出去的?下面我们带着这几个问题一起分析下NameServer
一,NameServer记录的信息
NameServer作为RocketMQ的注册中心,主要存储着队列与Topic关系列表,broker列表,集群与broker关系列表,当前存活的broker列表
public class RouteInfoManager {
//Broker向NameServer上报心跳的最大时间
private final static long BROKER_CHANNEL_EXPIRED_TIME = 1000 * 60 * 2;
private final ReadWriteLock lock = new ReentrantReadWriteLock();
//主题与队列的关系列表,其中队列里有读队列与写队列
private final HashMap<String/* topic */, List<QueueData>> topicQueueTable;
private final HashMap<String/* brokerName */, BrokerData> brokerAddrTable;//所有broker信息
private final HashMap<String/* clusterName */, Set<String/* brokerName */>> clusterAddrTable;//每个集群包括哪些broker
//当前存活broker,因为nameserver 10S扫描一次所以会有延迟
private final HashMap<String/* brokerAddr */, BrokerLiveInfo> brokerLiveTable;
//记录每个Broker分别使用了哪些消息过滤服务器
private final HashMap<String/* brokerAddr */, List<String>/* Filter Server */> filterServerTable;
}
- topicQueueTable:各topic属于那个broker上;每个topic下有多少队列;各队列的读写数量及权限
- brokerAddrTable:各broker id与address关系,会区分broker的master与slave
- clusterAddrTable:各cluster包含的broker
- brokerLiveTable:当前存活的broker,会有一定的延迟
- filterServerTable:每个Broker分别使用了哪些消息过滤服务器
如果上面的数据发生了变化NameServer如何处理呢?答案是通过BrokerHousekeepingService
进行监听,它实现了ChannelEventListener接口,如果通道发生了变动,比如Nameserver与 Broker的连接通道在关闭、通道发送异常、通道空闲时,会触发BrokerHousekeepingService的回调,然后移除相应的Broker。
二,NameServer的工作机制
RocketMQ的路由信息主要是指Topic的队列信息,也就是队列分布在哪个Broker里。
- NameServer 命名服务,集群部署,各节点间不通信
- Broker 消息服务器,每隔30S向NameServer发送心跳信息
- Producer,Consumer 消息客户端,同一时间内只会连一个NameServer服务器,每隔30S更新一次Topic信息
NameServer启动后会每隔10S扫描Broker集群,如果一定时间内(120S)内未收到Broker心跳信息,NameServer会将此Broker移除,以提高消息发送高可用。这就是典型的PULL模式,而ZK则是一种PUSH的模式,ZK是通过事件机制来实现的PUSH模式,这种模式一个优点就是具有实时性,一旦服务端有变动,客户端可以马上贴到ZK的通知,但这种强一制性是牺牲了可用性的,这会导致服务在一定时间内不可用。
但PULL模式也有它的问题,NameServer存储的路由信息如果发生了变化它不会主动通知客户端,面是需要客户端主动去拉取最新的路由信息(一定频率的定时任务拉取),这样显然是不及时的。RocketMQ是如何应对的呢?答案是通过客户端的重试与Broker的规避策略(可以参考前面写的RocketMQ学习四-消息发送高可用设计)。
我们可以分析下,如果NameServer集群信息不一致对消息发送端与消息消费端分别有什么影响。
- 对发送端的影响
假设有如下场景:
因为一些原因Namerserver-2里的broker信息只有broker-a可以使用,对于消息发送端的Producer-1可以将消息发送到broker-a与broker-b两个broker上且Consumer-2可以正常消费,而Producer-2则只能将消息发送到broker-a上且Consumer-1只能消费到broker-a上的消息,这样后果是压力全在broker-a上,但服务还是可用的,经过人工干预后问题可以解决。所以NameServer集群路由信息不一致并不会导致消息发送不可用。 - 对消费端的影响(待定,这一块需要看完broker与consumer之后再写,需要弄清楚重复消费)
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。