RocketMQ——Name Server篇

1 NameServer的功能

1、每個Broker啓動的時候會向Namesrv發送註冊請求,Namesrv接收Broker的請求註冊路由信息,NameServer保存活躍的broker列表,包括Master和Slave;

2、用來保存所有topic和該topic所有隊列的列表;

3、NameServer用來保存所有broker的Filter列表

4、接收client(Producer和Consumer)的請求根據某個topic獲取所有到broker的路由信息;

2 NameServer的初始化及啓動過程

1、KVConfigManager類加載NameServer的配置參數,配置參數的路徑是 $HOME /namesrv/kvConfig.json;將配置參數加載保存到KVConfigManager.configTable:HashMap<String/*namespace*/,HashMap<String/*key*/,String/*value*/>>變量中。

2、以初始化BrokerHousekeepingService對象爲參數初始化NettyRemotingServer對象,BrokerHousekeepingService對象作爲該Netty連接中Socket鏈接的監聽器(ChannelEventListener);監聽與Broker建立的渠道的狀態(空閒、關閉、異常三個狀態),並調用BrokerHousekeepingService的相應onChannel****方法。其中渠道的空閒、關閉、異常狀態均調用RouteInfoManager.onChannelDestory方法處理。清理RouteInfoManager類的幾個成員變量數據:

變量名稱 變量類型 含義
topicQueueTable HashMap<String/*topic*/, List<QueueData>> 主題與topic配置的對應關係,topics.json的topicConfigTable數據,在QueueData對象中記錄了該topic的BrokerName
brokerAddrTable HashMap<String/*brokerName*/, BrokerData> Broker名稱與broker屬性的map
clusterAddrTable HashMap<String/* clusterName */, Set<String/* brokerName */>> 集羣與broker集合的對應關係
brokerLiveTable HashMap<String/* brokerAddr */, BrokerLiveInfo> Broker的信息集合
filterServerTable HashMap<String/* brokerAddr */, List<String>/* Filter Server */> Borker地址與過濾器的集合

3、註冊默認的處理類DefaultRequestProcessor,所有的請求均由該處理類的processRequest方法來處理。

4、設置兩個定時任務:

第一是每隔10秒檢查一遍所有Broker的狀態的定時任務,調用scanNotActiveBroker方法;大致邏輯是:遍歷brokerLiveTable集合,查看每個broker的最後更新時間(BrokerLiveInfo.lastUpdateTimestamp)是否超過2分鐘,若超過則關閉該broker的渠道並調用RouteInfoManager.onChannelDestory方法清理RouteInfoManager類的topicQueueTable、brokerAddrTable、clusterAddrTable、filterServerTable成員變量。

第二是每隔10分鐘打印一次NameServer的配置參數。即KVConfigManager.configTable變量的內容。

5、啓動NameServer的Netty服務端(NettyRemotingServer),監聽渠道的請求信息。當收到客戶端的請求信息之後會初始化一個線程,並放入線程池中進行處理,該線程調用DefaultRequestProcessor. processRequest方法來處理請求。

請求的KEY值 作用
PUT_KV_CONFIG 向Namesrv追加KV配置
GET_KV_CONFIG 從Namesrv獲取KV配置
DELETE_KV_CONFIG 從Namesrv獲取KV配置
REGISTER_BROKER 註冊一個Broker,數據都是持久化的,如果存在則覆蓋配置
UNREGISTER_BROKER 卸載一個Broker,數據都是持久化的
GET_ROUTEINTO_BY_TOPIC 根據Topic獲取Broker Name、topic配置信息
GET_BROKER_CLUSTER_INFO 獲取註冊到Name Server的所有Broker集羣信息
WIPE_WRITE_PERM_OF_BROKER 去掉BrokerName的寫權限
GET_ALL_TOPIC_LIST_FROM_NAMESERVER 從Name Server獲取完整Topic列表
DELETE_TOPIC_IN_NAMESRV 從Namesrv刪除Topic配置
GET_KV_CONFIG_BY_VALUE 通過 project 獲取所有的 server ip 信息
DELETE_KV_CONFIG_BY_VALUE 刪除指定 project group 下的所有 server ip 信息
GET_KVLIST_BY_NAMESPACE 通過NameSpace獲取所有的KV List
GET_KVLIST_BY_NAMESPACE 通過NameSpace獲取所有的KV List
GET_TOPICS_BY_CLUSTER 獲取指定集羣下的所有 topic
GET_SYSTEM_TOPIC_LIST_FROM_NS 獲取所有系統內置 Topic 列表
GET_UNIT_TOPIC_LIST 單元化相關 topic
GET_HAS_UNIT_SUB_TOPIC_LIST 獲取含有單元化訂閱組的 Topic 列表
GET_HAS_UNIT_SUB_UNUNIT_TOPIC_LIST 獲取含有單元化訂閱組的非單元化 Topic 列表

3 處理Broker註冊請求

在接收到REGISTER_BROKER請求碼之後,由DefaultRequestProcessor.registerBroker(ChannelHandlerContext ctx, RemotingCommand request)方法處理註冊請求,在該方法中調用 RouteInfoManager.registerBroker(String clusterName, String brokerAddr, String brokerName, long brokerId, String haServerAddr, TopicConfigSerializeWrapper topicConfigWrapper, List<String> filterServerList, Channel channel)方法完成註冊處理邏輯,註冊完成後返回給Broker端主用Broker的地址,以及該主用Broker的HA服務地址。

1、維護RouteInfoManager.clusterAddrTable變量;若Broker集羣名字不在該Map變量中,則初始化一個Set集合,將brokerName存入該Set集合中,然後以clusterName爲key值,該Set集合爲values值存入此Map變量中;說明一個集羣下面有多個Broker;

2、維護RouteInfoManager.brokerAddrTable變量,該變量是維護Broker的名稱、ID、地址等信息的。若該brokername不在該Map變量中,則創建BrokerData對象,該對象包含了brokername,以及brokerId和brokerAddr爲K-V的brokerAddrs變量;然後以brokername爲key值將BrokerData對象存入該brokerAddrTable變量中;說明同一個BrokerName下面可以有多個不同BrokerId的Broker存在,表示一個BrokerName有多個Broker存在,通過BrokerId來區分主備。

3、若Broker的註冊請求消息中topic的配置不爲空,並且該Broker是主用(即brokerId=0),則根據NameServer存儲的Broker版本信息來判斷是否需要更新NameServer端的topic配置信息。若是第一個註冊,即表示Name Server端還沒有該Broker的topic信息,或者在NameServer中維護的該Broker的dataversion與收到的topic配置(TopicConfigSerializeWrapper)的dataversion不一致;則更新NameServer端的topic配置信息。大致處理思路:

遍歷TopicConfigSerializeWrapper對象的topicConfigTable變量,以該變量中的每個TopicConfig對象以及該Broker的名稱爲參數調用RouteInfoManager.createAndUpdateQueueData(String brokerName, TopicConfig topicConfig) 方法,該方法的邏輯是:

A)用TopicConfig對象中的各變量來初始化QueueData對象,包括的變量有:brokerName、讀寫隊列數、權限等信息;

B)維護RouteInfoManager.topicQueueTable變量,該變量是維護topic配置信息的。以topic的名字從RouteInfoManager.topicQueueTable變量中獲取QueueData列表;若沒有則初始化該QueueData隊列並將上一步初始化的QueueData對象存入;若已經存在QueueData隊列,則遍歷該隊列中的每個QueueData對象,檢查是否與該註冊的Broker相同的名字的QueueData對象:

若相同則檢查該QueueData對象的各個屬性值是否與新創建的QueueData對象(在第A步中創建的)一致,若一致則表示是topic的配置沒有變化則不更新QueueData隊列的該QueueData對象,若不一致,則認爲該topic有變化,要將該QueueData對象從QueueData列表中刪除,然後將新創建的QueueData對象加入到此隊列中;

若不相同則直接將QueueData對象加入到此QueueData隊列中;

4、初始化BrokerLiveInfo 對象並以broker地址爲key值存入brokerLiveTable:HashMap<String/* brokerAddr */, BrokerLiveInfo>變量中;

5、對於filterServerList不爲空的,以broker地址爲key值存入RouteInfoManager.filterServerTable :HashMap<String/* brokerAddr */, List<String>/* Filter Server */>變量中;

6、找到該BrokerName下面的主用Broker(BrokerId=0),方法是以該Brokerame從RouteInfoManager.BrokerAddrTable變量中獲取BrokerData對象,然後取該對象的brokerAddrs變量,從該變量中找到BrokerId=0的Broker地址,作爲該註冊Broker對應的主用地址MasterAddr; 以主用Broker地址從brokerLiveTable中獲取BrokerLiveInfo 對象,取該對象的HaServerAddr 值,將該地址作爲HaServerAddr返回給Broker端,即主用Broker的HaServerAddr爲其他備用Broker的HAClient.masterAddress值。

4 根據Topic獲取Broker信息和topic配置信息(getRouteInfoByTopic)

當NameServer收到GET_ROUTEINTO_BY_TOPIC 請求碼之後,間接調用了RouteInfoManager.pickupTopicRouteData(String topic)方法獲取Broker信息和topic配置信息。

1、獲取topic配置信息,根據topic從RouteInfoManager.topicQueueTable變量中獲取List<QueueData>隊列,賦值給返回對象TopicRouteData的QueueDatas變量。表示該topic對應的所有topic配置信息以及每個配置所屬的BrokerName。

2、從上一步獲取到的List<QueueData>隊列中獲取BrokerName集合,該集合是去重之後的BrokerName集合,然後以該BrokerName集合的每個BrokerName從RouteInfoManager.brokerAddrTable變量中獲取BrokerData對象,將所有獲取到的BrokerData對象集合賦值給返回對象TopicRouteData的BrokerDatas集合變量。表示該topic是由哪些Broker提供的服務,以及每個Broker的名字、BrokerId、IP地址。

然後以"ORDER_TOPIC_CONFIG"和請求消息中的topic值爲參數從NamesrvController.kvConfigManager.configTable: HashMap<String/* Namespace */, HashMap<String/* Key */, String/* Value */>>變量中獲取orderTopiconf值(即broker的順序),並賦值給TopicRouteData.orderTopicConf變量;該orderTopiconf的參數格式爲:以";"解析成數組,數組的每個成員是以":"分隔的,構成數據"brokerName:queueNum";

最後將TopicRouteData對象返回給調用者;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章