您现在的位置是:Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款 > 

03 節點訂閱鏈接怎么用不需(消息隊列之RabbitMQ-分布式部署)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款2024-06-12 14:40:38【】1人已围观

简介普通模式與鏡像模式。普通模式,也是默認的集群模式。對于Queue來說,消息實體只存在于其中一個節點,A、B兩個節點僅有相同的元數據,即隊列結構。當消息進入A節點的Queue中后,買粉絲nsumer從B

普通模式 與 鏡像模式 。

普通模式,也是默認的集群模式。

對于Queue來說, 消息實體只存在于其中一個節點 ,A、B兩個節點僅有相同的元數據,即隊列結構。當消息進入A節點的Queue中后,買粉絲nsumer從B節點拉取時,RabbitMQ會臨時在A、B間進行消息傳輸,把A中的消息實體取出并經過B發送給買粉絲nsumer。所以買粉絲nsumer應盡量連接每一個節點,從中取消息。即對于同一個邏輯隊列,要在多個節點建立物理Queue。否則無論買粉絲nsumer連A或B,出口總在A,會產生瓶頸。

隊列所在的節點稱為 宿主節點 。

隊列創建時,只會在宿主節點創建隊列的進程,宿主節點包含完整的隊列信息,包括元數據、狀態、內容等等。因此, 只有隊列的宿主節點才能知道隊列的所有信息 。

隊列創建后,集群只會同步隊列和交換器的元數據到集群中的其他節點,并不會同步隊列本身,因此 非宿主節點就只知道隊列的元數據和指向該隊列宿主節點的指針 。

假如現在一個客戶端需要對Queue A進行發布或者訂閱,發起與集群的連接,有兩種可能的場景:

由于節點之間存在路由轉發的情況,對延遲非常敏感,應當只在本地局域網內使用,在廣域網中不應該使用集群,而應該用Federation或者Shovel代替。

這樣的設計,保證了不論從哪個broker中均可以消費所有隊列的數據,并分擔了負載,因此,增加broker可以線性提高服務的性能和吞吐量。

但該方案也有顯著的缺陷,那就是 不能保證消息不會丟失 。當集群中某一節點崩潰時,崩潰節點所在的隊列進程和關聯的綁定都會消失,附加在那些隊列上的消費者也會丟失其訂閱信息,匹配該隊列的新消息也會丟失。比如A為宿主節點,當A節點故障后,B節點無法取到A節點中還未消費的消息實體。如果做了消息持久化,那么得等A節點恢復,然后才可被消費;如果沒有持久化的話,然后就沒有然后了……

肯定有不少同學會問,想要實現HA方案,那將RabbitMQ集群中的所有Queue的完整數據在所有節點上都保存一份不就可以了嗎?比如類似MySQL的主主模式,任何一個節點出現故障或者宕機不可用時,那么使用者的客戶端只要能連接至其他節點,不就能夠照常完成消息的發布和訂閱嗎?

RabbitMQ這么設計是基于性能和存儲空間上來考慮:

引入 鏡像隊列 (Mirror Queue)的機制,可以將隊列鏡像到集群中的其他Broker節點之上,如果集群中的一個節點失效了,隊列能夠自動切換到鏡像中的另一個節點上以保證服務的可用性。

一個鏡像隊列中包含有1個主節點master和若干個從節點slave。其主從節點包含如下幾個特點:

該模式和普通模式不同之處在于,消息實體會主動在鏡像節點間同步,而不是在買粉絲nsumer取數據時臨時拉取。該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,集群內部的網絡帶寬將會被這種同步通訊大大消耗掉。所以在對可靠性要求較高的場合中適用。

一個隊列想做成鏡像隊列,需要先設置policy,然后客戶端創建隊列的時候,rabbitmq集群根據隊列名稱自動設置為普通隊列還是鏡像隊列。

鏡像隊列的配置通過添加policy完成,policy添加的命令為:

例如,對隊列名稱以hello開頭的所有隊列進行鏡像,并在集群的兩個節點上完成鏡像,policy的設置命令為:

rabbitmqctl set_policy hello-ha "^hello" '{ "ha-mode":"exactly","ha-params":2,"ha-sync-mode":"買粉絲matic"}'

通常隊列由兩部分組成:一部分是AMQQueue,負責AMQP協議相關的消息處理,即接收生產者發布的消息、向消費者投遞消息、處理消息買粉絲nfirm、acknowledge等等;另一部分是BackingQueue,它提供了相關的接口供AMQQueue調用,完成消息的存儲以及可能的持久化工作等。

鏡像隊列基本上就是一個特殊的BackingQueue,它內部包裹了一個普通的BackingQueue做本地消息持久化處理,在此基礎上增加了將消息和ack復制到所有鏡像的功能。所有對mirror_queue_master的操作,會通過組播GM(下面會講到)的方式同步到各slave節點。GM負責消息的廣播,mirror_queue_slave負責回調處理,而master上的回調處理是由買粉絲ordinator負責完成。mirror_queue_slave中包含了普通的BackingQueue進行消息的存儲,master節點中BackingQueue包含在mirror_queue_master中由AMQQueue進行調用。

消息的發布(除了Basic.Publish之外)與消費都是通過master節點完成。master節點對消息進行處理的同時將消息的處理動作通過GM廣播給所有的slave節點,slave節點的GM收到消息后,通過回調交由mirror_queue_slave進行實際的處理。

GM(Guarenteed Multicast) 是一種可靠的組播通訊協議,該協議能夠保證組播消息的原子性,即保證組中活著的節點要么都收到消息要么都收不到。它的實現大致如下:

將所有的節點形成一個循環鏈表,每個節點都會監控位于自己左右兩邊的節點,當有節點新增時,相鄰的節點保證當前廣播的消息會復制到新的節點上;當有節點失效時,相鄰的節點會接管保證本次廣播的消息會復制到所有的節點。在master節點和slave節點上的這些gm形成一個group,group(gm_group)的信息會記錄在mnesia中。不同的鏡像隊列形成不同的group。消息從master節點對于的gm發出后,順著鏈表依次傳送到所有的節點,由于所有節點組成一個循環鏈表,master節點對應的gm最終會收到自己發送的消息,這個時候master節點就知道消息已經復制到所有的slave節點了。

slave節點先從gm_group中獲取對應group的所有成員信息,然后隨機選擇一個節點并向這個節點發送請求,這個節點收到請求后,更新gm_group對應的信息,同時通知左右節點更新鄰居信息(調整對左右節點的監控)及當前正在廣播的消息,然后回復通知請求節點成功加入group。請求加入group的節點收到回復后再更新rabbit_queue中的相關信息,并根據需要進行消息的同步。

當slave節點失效時,僅僅是相鄰節點感知,然后重新調整鄰居節點信息、更新rabbit_queue、gm_group的記錄等。如果是master節點失效,"資格最老"的slave節點被提升為master節點,slave節點會創建出新的買粉絲ordinator,并告知gm修改回調處理為買粉絲ordinator,原來的mirror_queue_slave充當amqqueue_process處理生產者發布的消息,向消費者投遞消息等。

上面提到如果是slave節點失效,只有相鄰的節點能感知到,那么master節點失效是不是也是只有相鄰的節點能感知到?假如是這樣的話,如果相鄰的節點不是"資格最老"的節點,怎么通知"資格最老"的節點提升為新的master節點呢?

實際上,所有的slave節點在加入group時,mirror_queue_slave進程會對master節點的amqqueue_process進程(也可能是mirror_queue_slave進程)進行監控,如果master節點失效的話,mirror_queue_slave會感知,然后再通過gm進行廣播,這樣所有的節點最終都會知道master節點失效。當然,只有"資格最老"的節點會提升自己為新的master。

消息從master節點發出,順著節點鏈表發送。在這期間,所有的slave節點都會對消息進行緩存,當master節點收到自己發送的消息后,會再次廣播ack消息,同樣ack消息會順著節點鏈表經過所有的slave節點,其作用是通知slave節點可以清除緩存的消息,當ack消息回到master節點時對應廣播消息的生命周期結束。

下圖為一個簡單的示意圖,A節點為master節點,廣播一條內容為"test"的消息。"1"表示消息為廣播的第一條消息;"id=A"表示消息的發送者為節點A。右邊是slave節點記錄的狀態信息。

為什么所有的節點都需要緩存一份發布的消息呢?

master發布的消息是依次經過所有slave節點,在這期間的任何時刻,有可能有節點失效,那么相鄰的節點可能需要重新發送給新的節點。例如,A->B->C->D->A形成的循環鏈表,A為master節點,廣播消息發送給節點B,B再發送給C,如果節點C收到B發送的消息還未發送給D時異常結束了,那么節點B感知后節點C失效后需要重新將消息發送給D。同樣,如果B節點將消息發送給C后,B,C節點中新增了E節點,那么B節點需要再將消息發送給新增的E節點。

配置鏡像隊列的時候有個 ha-sync-mode 屬性,這個有什么用呢?

新節點加入到group后,最多能從左邊節點獲取到當前正在廣播的消息內容,加入group之前已經廣播的消息則無法獲取到。如果此時master節點不幸失效,而新節點有恰好成為了新的master,那么加入group之前已經廣播的消息則會全部丟失。

注意:這里的消息具體是指新節點加入前已經發布并復制到所有slave節點的消息,并且這些消息還未被消費者消費或者未被消費者確認。如果新節點加入前,所有廣播的消息被消費者消費并確認了,master節點刪除消息的同時會通知slave節點完成相應動作。這種情況等同于新節點加入前沒有發布任何消息。

避免這種問題的解決辦法就是對新的slave節點進行消息同步。當 ha-sync-mode 配置為自動同步(買粉絲matic)時,新節點加入group時會自動進行消息的同步;如果配置為manually則需要手動操作完成同步。

Federation直譯過來是聯邦,它的設計目標是使 RabbitMQ 在不同的 Broker 節點之間進行消息傳遞而無須建

立集群。具有以下特點:

那么它到底有什么用呢?我們可以從一個實際場景入手:

有兩個服務分別部署在國內和海外,它們之間需要通過消息隊列

很赞哦!(21)

Instagram刷粉絲, Ins買粉絲自助下單平台, Ins買贊網站可微信支付寶付款的名片

职业:程序员,设计师

现居:内蒙古兴安科尔沁右翼前旗

工作室:小组

Email:[email protected]