3

RocketMQ学习八-NameServer分析

 2 years ago
source link: https://segmentfault.com/a/1190000041362477
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

RocketMQ学习八-NameServer分析

发布于 2 月 2 日

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集群信息不一致对消息发送端与消息消费端分别有什么影响。

  1. 对发送端的影响
    假设有如下场景:
    image.png
    因为一些原因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集群路由信息不一致并不会导致消息发送不可用。
  2. 对消费端的影响(待定,这一块需要看完broker与consumer之后再写,需要弄清楚重复消费)

参考的文章:
RocketMQ4.0源码分析之-路由管理
Nameserver 背后的设计理念


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK