暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

RocketMQ中NameServer的设计

程序猿研习社 2021-09-06
835

先来看一下RocketMQ整体架构

Producer:生产者

Consumer:消费者

Broker:消息存储

NameServer:topic路由(broker的注册中心)

Broker消息服务器在启动时向所有NameServer注册,消息生产者(Producer)在发送消 息之前先从 NameServer 获取 Broker 服务器地址列表,然后根据负载算法从列表中选择一台消息服务器进行消息发送 。NameServer 与每台 Broker 服务器保持长连接,并间隔30s检测Broker是否存活,如果检测到Broker宕机 , 则从路由注册表中将其移除 。


下面我们带着问题去看NameServer的架构设计,为了避免消息服务器的单点故障,通常会部署多台消息服务器(broker)共同承担消息的存储 。

  1. 那么消息生产者如何知道消息要发往哪台消息服务器呢?

  2. 如果某一台消息服务器若机了,那么生产者如何在不重启服务的情况下感知呢?



我们直接从源码看NameServer 路由注册、路由删除、路由发现

打开RocketMQ源码,目录如下图,其中保存路由信息的就是这几个关键的HashMap

  • topicQueueTable: Topic消息队列路由信息,消息发送时根据路由表进行负载均衡,debug代码截图如下        

  • brokerAddrTable : Broker基础信息, 包含brokerName、 所属集群名称 、 主备Broker地址,debug代码截图如下

  • clusterAddrTable: Broker集群信息,存储集群中所有Broker名称

  • brokerLiveTable: Broker状态信息 。NameServer每次收到心跳包时会替换该信息

  • filterServerTable : Broker上的FilterServer列表,用于消息过滤


路由注册

(1)broker发送心跳包

Broker启动时向集群中所有的NameServer发送心跳包,每隔30s向 集群中所有 NameServer发送一次,NameServer收到Broker心跳包时会更新brokerLiveTable缓存中BrokerLivelnfo的lastUpdateTimestamp,然后NameServer每隔10s扫描 brokerLiveTable,如果连续120s没有收到心跳包, NameServer将移除该Broker的路由信息同时关闭Socket连接。broker在启动时,会启动定时任务来发送心跳包到NameServer,如下图


(2)NameServer处理心跳包

RockerMQ使用的是Netty通信,这里提一嘴,如下面代码所示,NameServer在启动时会启动一个线程不断执行processRequest,接收产生的请求(事件),由对应的时间处理器(switch语句分支)来执行

跟踪进入registerBroker方法:主要会更新NameServer保存的broker发送的最后一次心跳包时间

设计亮点: NameServer和Broker保持长连接,Broker状态存储在brokerLiveTable 中,NameServer每收到一个心跳包,将更新brokerLiveTable中关于Broker的状态信息以及路 由表( topicQueueTable、brokerAddrTable、brokerLiveTable、filterServerTable)。更新上述路由表(HashTable)使用了锁粒度较小的读写锁,允许多个消息发送者(Producer)并发读,保证消息发送时的高并发。但同一时刻NameServer只处理一个Broker心跳包,多个心跳包请求串行执行。这也是读写锁经典使用场景


路由删除

Broker每隔30s向NameServer 发送一个心跳包,NameServer会每隔10s扫描 brokerLiveTable状态表,如果BrokerLive的lastUpdateTimestamp的时间戳距当前时间超过120s,则认为Broker失效,移除该Broker, 关闭与Broker连接,并同时更新上面说的那四个HashMap;

RocktMQ 有两个触发点来触发路由删除:

  1. NameServer定时扫描 brokerLiveTable检测上次心跳包与 当前系统时间的时间差, 如果时间戳大于 120s,则需要移除该 Broker 信息 。

  2.  Broker在正常被关闭的情况下,会执行 unr巳gisterBroker指令。由于不管是何种方式触发的路由删除,路由删除的方法都是一样的,就是从 topic­


核心的就是一个scanNotActiveBroker的方法,定时任务(NameServer启动时加载)10秒执行一次


路由发现

RocketMQ的Topic路由信息发生变化时,不会主动通知客户端(生产者和消费者),而是由生产者定时拉取,由DefaultRequestProcessor来处理


总结:上面的讲解可以由下面一张图来形象表示

另外:NameServer需要等Broker失效至少120s才能将该Broker从路由表中移除掉,那如果在Broker故障期间,消息生产者 Producer根据主题获取到的路由信息包含已经看机的 Broker,会导致消息发送失败,那这种情况怎么办,岂不是消息发送不是高可用的?(且听下回分享😝)

文章转载自程序猿研习社,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论