從RocketMQ我們學到了什麼?(NameServer篇)

微信公衆號:IT一刻鐘
大型現實非嚴肅主義現場
一刻鐘與你分享優質技術架構與見聞,做一個有劇情的程序員
關注可瞭解更多精彩內容。問題或建議,請公衆號留言。

在這裏插入圖片描述

在很久很久以前,人們之間的通信方式就是面對面交談,你說一句,我聽一句,雖然簡單可靠,但是弊端也很大。
比如,當你成爲一個軍隊的首領,每個屬下一有情況就立刻向你彙報,一個還好,但當你的屬下有幾十個幾百個的時候,他們每天不分時間不看場合,都在嘰嘰喳喳和你彙報情況,那你可能什麼都聽不到,而且腦袋都要炸掉了。這個時候,你說停,都給我停下,要彙報情況的,去門口排隊,一個一個的來,這個就叫做流量削峯,一羣人不要一擁而上,都乖乖給我排隊去。
然後你就一個接一個的聽,聽了整整24個小時,實在困的不行,尋思着這樣不行呀,如此下去可能就要天妒英才了,於是你又說,來人,發筆和紙,都把要彙報的消息寫在紙上,寫完後告訴呂秀才,然後聽呂秀才的指示,沿着屋裏右面牆根,按照指示的位置疊放整齊,彙報的人就可以退下該做啥做啥去吧,等我休息一下,再來看你們的彙報內容,這就叫做異步處理,你終於可以由自己掌控消息獲取的進度了,美滋滋的去睡覺了。
而彙報的人把內容寫在紙上,疊放好,就可以退下自己做自己該做的事情,而不是一直在門口等待彙報,這個就叫做解耦。
削峯,異步,解耦。這就是消息隊列最常用的三大場景。
故事中的下屬們,就是消息生產者角色,屋子右面牆根那塊地就是消息持久化,呂秀才就是消息調度中心,而你就是消息消費者角色。下屬們彙報的消息,應該疊放在哪裏,這個消息又應該在哪裏才能找到,全靠呂秀才的驚人記憶力,纔可以讓消息準確的被投放以及消費。

消息調度中心是今天的主角

在RocketMQ裏,就有一個角色和呂秀才的作用一樣,叫做NameServer,它是整個分佈式消息調度的總控制,是RocketMQ的靈魂之所在,倘如沒有了它,RocketMQ會分崩離析無法工作。
那麼,它是怎麼工作的呢?
我們先來看一張RocketMQ屋裏架構圖:
在這裏插入圖片描述
亂如蜘蛛絲?不要害怕,換句話說,先忘掉這張圖吧。

我們來類比一下現實生活,有一個人想要給另外一個人寄快件,那麼就需要先由這個人在網上查詢有哪些郵局,然後選擇其中一個郵局,把快件投遞給它,再由郵局配送到目標人。
在這裏插入圖片描述
需要完成這一整個業務流程,首先需要將郵局自身的信息註冊到衛星網絡上,衛星負責信息的調度,這樣發件人就知道有哪些郵局可以選擇,收件人通過衛星網絡知道快件到了哪個郵局,可以聯繫郵局溝通適合的配送時間,而郵局則負責接收配送存儲快件。
類比RocketMQ簡線圖就是如下:
在這裏插入圖片描述
Producer:消息⽣產者,⽤於向消息服務器發送消息,就是圖中的寄件人。
NameServer:路由註冊中⼼,就是圖中的衛星。
Broker:消息存儲服務器,就是圖中的郵局。
Consumer:消息消費者,不是今天的重點,圖中未標出,就是收件人。

由此可見,NameServer作爲分佈式消息隊列的協調者,具有信息路由註冊與發現的作用。

路由註冊

郵局在竣工後,需要與衛星聯網,將自己納入衛星網絡管理中,這樣就相當於對外宣佈,我這個郵局開始運營了,可以收發郵件快遞了。
郵局併網之後,如何讓衛星持續並及時感知這個郵局在線以及郵局自身信息的調整,使衛星可以隨時協調這個郵局呢?這個時候就需要郵局定時向衛星發一條信息:
“嗶嗶嗶————我是郵局C,編號SHC,地址XXXXX,歸屬中國上海集羣,在線,此時此刻2019年3月15日13點21秒”
衛星接收到消息後,拿個小本本記錄下來:
“郵局B,BJB,北京,2019年3月15日13點10秒,活着…”
“郵局A,BJA,北京,2019年3月15日13點15秒,活着…”
“郵局C,SHC,上海,2019年3月15日13點21秒,活着…”

在這裏插入圖片描述
上面這個故事,就講述了NameServer路由註冊的基本原理。
NameServer就相當於衛星,內部會維護一個Broker表,用來動態存儲Broker的信息。
而Broker就相當於郵局,在啓動的時候,會先遍歷NameServer列表,依次發起註冊請求,保持長連接,然後每隔30秒向NameServer發送心跳包,心跳包中包含BrokerId、Broker地址、Broker名稱、Broker所屬集羣名稱等等,然後NameServer接收到心跳包後,會更新時間戳,記錄這個Broker的最新存活時間。
NameServer在處理心跳包的時候,存在多個Broker同時操作一張Broker表,爲了防止併發修改Broker表導致不安全,路由註冊操作引入了ReadWriteLock讀寫鎖,這個設計亮點允許多個消息生產者併發讀,保證了消息發送時的高併發,但是同一時刻NameServer只能處理一個Broker心跳包,多個心跳包串行處理。這也是讀寫鎖的經典使用場景,即讀多寫少。

路由剔除

在這裏插入圖片描述
忽然有一天,郵局C的機房進老鼠了,咬斷電源線宕機了,而衛星不知道郵局C業務故障了,依舊將帶有郵局C的郵局表信息傳給寄件人(生產者),寄件人聯繫郵局C發送快件,但是郵局C機房宕機,業務暫停,處於癱瘓狀態,自然也就無法接收快件了。
另一方面,因爲快件未能被郵局C收入,也就無法將快件轉交給收件人,顧客們久久等不到自己的快件,紛紛投訴,爲此郵局C的管理層備受責難。
於是郵政總局技術部開始研究討論,怎麼讓衛星可以感知到郵局“失聯了”,從而自動排除故障郵局,將其負責的業務交付給其他正常的郵局處理,這樣就不會因爲某一個郵局出現問題,而導致這個郵局所管轄的部分業務無法處理。
大家衆說紛紜,最後敲定了一個方案,讓衛星每隔一段時間掃描郵局信息表,如果發現某個郵局上報信息時間與當時掃描時間之間的差值超過了某個預設的閾值,就判定這個郵局“失聯了”,將此郵局信息從郵局表中剔除。這樣寄件人查詢到的郵局表裏都是正常營業的郵局信息。
新功能上線運營後,效果不錯,大家再也不用擔心因爲某個郵局故障而導致業務停滯,又過上了泡茶報紙的生活。

這個故事同樣在RocketMQ中上演。
正常情況下,如果Broker關閉,則會與NameServer斷開長連接,Netty的通道關閉監聽器會監聽到連接斷開事件,然後會將這個Broker信息剔除掉。
異常情況下,NameServer中有一個定時任務,每隔10秒掃描一下Broker表,如果某個Broker的心跳包最新時間戳距離當前時間超多120秒,也會判定Broker失效並將其移除。

細心的人會發現一個問題,NameServer在清除失活Broker之後,並沒有主動通知生產者,生產者每隔30秒會請求NameServer並獲取最新的路由表,那麼就意味着,消息生產者總會有30秒的延時,無法實時感知Broker服務器的宕機。所以在這個30秒裏,生產者依舊會向失活Broker發送消息,那麼消息發送的高可用性如何保證呢?
要解決這個問題得首先談一談Broker的負載策略,消息發送隊列默認採用輪詢機制,消息發送時默認選擇異常重試機制來保證消息發送的高可用。當Broker宕機後,雖然消息發送者無法第一時間感知Broker 宕機,但是當消息生產者向Broker發送消息返回異常後,消息生產者會選擇另外一個Broker上的消息隊列,這樣就規避了發生故障的Broker,結合重試機制,巧妙實現消息發送的高可用,同時由於不需要NameServer通知衆多不固定的生產者,也降低了NameServer實現的複雜性。

在降低NameServer實現複雜性方面,還有一個設計亮點就是NameServer之間是彼此獨立無交流的,也就是說NameServer服務器之間在某個時刻的數據並不會完全相同,但是異常重試機制使得這種差異不會造成任何影響。
在這裏插入圖片描述

路由發現

天上的衛星是有限的,不易變的,而地上的寄件人是繁多的,易變的。所以寄件人想要知道有哪些郵局,很明顯最適合的方式是向衛星發請求,拉取郵局表信息,而不是等衛星給每個人推送。
所以在RocketMQ中,NameServer是不主動推送會客戶端的,而是由客戶端拉取主題的最新路由信息。
在這裏插入圖片描述

CAP理論

NameServer作爲註冊和發現中心,是整個分佈式消息隊列調度的靈魂,談及到分佈式,就逃不開CAP理論,C是Consistency,A是Availability,P是Partiton Tolerance,對於分佈式架構,網絡條件不可控,出現網絡分區是不可避免的,因此必須具備分區容錯性,那麼NameServer就是在AP還是CP中選擇了,由於NameServer之間相互獨立,很明顯,是一個AP設計。

之所以替換掉Zookeeper

ZooKeeper爲分佈式應用程序提供協調服務。那爲什麼RocketMQ要自己造輪子,開發集羣的管理程序呢?因爲ZooKeeper的功能很強大,包括自動Master選舉等,RocketMQ的架構設計決定了它不需要進行Master選舉,用不到這些複雜的功能,只需要一個輕量級的元數據服務器就足夠了。
中間件對穩定性要求很高,RocketMQ的NameServer只有很少的代碼,容易維護,所以不需要再依賴另一箇中間件,從而減少整體維護成本。

學到了什麼?

1.長連接編程模型⾥⼼跳的實現原理
2.多線程編程中讀寫鎖的經典使⽤⽅式
3.追求簡單⾼效⼜可靠的實現⽅式

說在後面的話

想要研究NameServer源代碼的,請點擊鏈接:https://github.com/MrChiu/RocketMQ-Study/tree/release-4.3.2/namesrv
裏面附有我標註的註釋,易於通讀代碼


在這裏插入圖片描述

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