摘要:故事中的下屬們,就是消息生產者角色,屋子右面墻根那塊地就是消息持久化,呂秀才就是消息調度中心,而你就是消息消費者角色。下屬們匯報的消息,應該疊放在哪里,這個消息又應該在哪里才能找到,全靠呂秀才的驚人記憶力,才可以讓消息準確的被投放以及消費。
微信公眾號: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是不主動推送會客戶端的,而是由客戶端拉取主題的最新路由信息。
NameServer作為注冊和發現中心,是整個分布式消息隊列調度的靈魂,談及到分布式,就逃不開CAP理論,C是Consistency,A是Availability,P是Partiton Tolerance,對于分布式架構,網絡條件不可控,出現網絡分區是不可避免的,因此必須具備分區容錯性,那么NameServer就是在AP還是CP中選擇了,由于NameServer之間相互獨立,很明顯,是一個AP設計。
之所以替換掉ZookeeperZooKeeper為分布式應用程序提供協調服務。那為什么RocketMQ要自己造輪子,開發集群的管理程序呢?因為ZooKeeper的功能很強大,包括自動Master選舉等,RocketMQ的架構設計決定了它不需要進行Master選舉,用不到這些復雜的功能,只需要一個輕量級的元數據服務器就足夠了。
中間件對穩定性要求很高,RocketMQ的NameServer只有很少的代碼,容易維護,所以不需要再依賴另一個中間件,從而減少整體維護成本。
1.長連接編程模型??跳的實現原理
2.多線程編程中讀寫鎖的經典使??式
3.追求簡單?效?可靠的實現?式
想要研究NameServer源代碼的,請點擊鏈接:https://github.com/MrChiu/Roc...
里面附有我標注的注釋,易于通讀代碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/73801.html
摘要:故事中的下屬們,就是消息生產者角色,屋子右面墻根那塊地就是消息持久化,呂秀才就是消息調度中心,而你就是消息消費者角色。下屬們匯報的消息,應該疊放在哪里,這個消息又應該在哪里才能找到,全靠呂秀才的驚人記憶力,才可以讓消息準確的被投放以及消費。 微信公眾號:IT一刻鐘大型現實非嚴肅主義現場一刻鐘與你分享優質技術架構與見聞,做一個有劇情的程序員關注可了解更多精彩內容。問題或建議,請公眾號留言...
摘要:所以基于目前的設計,建議關閉自動創建的功能,然后根據消息量的大小,手動創建。如果發送消息,返回結果超時,這種超時不會進行重試了如果是方法本身耗時超過,還未來得及調用發送消息,此時的超時也不會重試。 先來看下producer核心的類設計,如下圖: showImg(http://pbdqyl9hh.bkt.clouddn.com/rocketmq/producer%E7%B1%BB%E5%...
摘要:它是阿里巴巴于年開源的第三代分布式消息中間件。是一個分布式消息中間件,具有低延遲高性能和可靠性萬億級別的容量和靈活的可擴展性,它是阿里巴巴于年開源的第三代分布式消息中間件。上篇文章消息隊列那么多,為什么建議深入了解下RabbitMQ?我們講到了消息隊列的發展史:并且詳細介紹了RabbitMQ,其功能也是挺強大的,那么,為啥又要搞一個RocketMQ出來呢?是重復造輪子嗎?本文我們就帶大家來詳...
摘要:當接收到消息后,會在方法中調用方法,將的信息塞進緩存中,并且會定時發送心跳將發送給進行注冊。這也說明了當用集群模式去創建時,集群里面每個的的數量相同,當用單個模式去創建時,每個的數量可以不一致。 微信公眾號「后端進階」,專注后端技術分享:Java、Golang、WEB框架、分布式中間件、服務治理等等。 老司機傾囊相授,帶你一路進階,來不及解釋了快上車! 我還記得第一次使用rocket...
摘要:前提通過前面兩篇文章可以簡單的了解和安裝,今天就將和整合起來使用。然后我運行之前的整合項目,查看監控信息如下總結整篇文章講述了與整合和監控平臺的搭建。 showImg(https://segmentfault.com/img/remote/1460000013232432?w=1920&h=1277); 前提 通過前面兩篇文章可以簡單的了解 RocketMQ 和 安裝 RocketMQ...
閱讀 3393·2021-09-22 15:01
閱讀 524·2019-08-30 11:11
閱讀 950·2019-08-29 16:17
閱讀 1209·2019-08-29 12:23
閱讀 2022·2019-08-26 11:48
閱讀 3176·2019-08-26 11:48
閱讀 1415·2019-08-26 10:33
閱讀 1927·2019-08-26 10:30