rabbitmq 學習與實踐分享之網路分割槽

zxhy發表於2019-04-25

前言

上一篇文章簡單的介紹了一下通過docker搭建rabbitmq叢集的過程。本文主要介紹一 下rabbitmq 叢集針對網路分割槽的應對策略,主要針對以下幾個問題展開:

  • 什麼是網路分割槽?
  • 為什麼會出現網路分割槽?如何模擬?
  • 網路分割槽對rabbitmq的消費者,生產者有什麼影響?
  • rabbitmq 如何應對網路分割槽?

一.什麼是網路分割槽?

在分散式系統中,不同的節點分佈在不同的子網路中,由於一些特殊的原因,這些子節點之間出現了網路不通的狀態,但他們的內部子網路是正常的。從而導致了整個系統的環境被切分成了若干個孤立的區域,這就是網路分割槽。針對rabbitmq 而言,出現網路分割槽時,處於子網中的節點會認為不處於自身分割槽的節點都down了,針對交換器,佇列,繫結關係等操作都只對當前分割槽有效。

二.為什麼會出現網路分割槽?

出現網路分割槽的原因有很多,比如網路卡故障,網路閃斷等等導致子網間網路不通。rabbitmq 內部節點預設會通過25672埠進行彼此間資訊交換,如果每隔1/4的net_ticktime 時間進行一次應答時,連續4次出現應答不上,則會認為彼此間網路不通,就會出現部分節點被剝離出當前分割槽,進而形成網路分割槽;

 預設配置檔案第361行: %% {net_ticktime, 60} 
複製程式碼

docker 模擬網路分割槽

首先假設以及搭建起了由myrabbit1,myrabbit2,myrabbit3 3個節點構成的叢集,如下所示:叢集中包含3個disc 型別的節點

 root@rabbit3:/# rabbitmqctl cluster_status
  Cluster status of node rabbit@rabbit3 ...
 [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]},
 {cluster_name,<<"rabbit@rabbit3">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]},{rabbit@rabbit3,[]}]}]
複製程式碼

通過docker pause 命令暫停其中的一個docker程式,過一段時間之後再unpause 該容器,模擬net_ticktime 超時.

rabbitmq 學習與實踐分享之網路分割槽
如圖所示發現出現了2個分割槽,通過rabbitmq 的管理介面也能夠感知到分割槽的存在,如圖所示:

rabbitmq 學習與實踐分享之網路分割槽

三.網路分割槽出現對訊息的生產者和消費者會產生什麼影響呢?

分2種情況討論:

  • 不存在映象佇列
  • 存在映象佇列

不存在映象佇列的情況:

場景1:

生產者客戶端 節點名稱 交換器 繫結key 佇列 client1 nodel ex key1 queue1 client2 node2 ex key2 queue2

說明一下:   
> 這種場景表示生產者客戶端1 連線到節點1上,通過路由key1 傳送訊息的exchange中,最終訊息被路由到queue1(queue1也是定義在node1上);
> 生產者客戶端2 連線到節點2上,通過路由key2 傳送訊息的exchange中,最終訊息被路由到queue2(queue2也是定義在node2上)
複製程式碼

在這種情況下,不管是否出現網路分割槽,對生產者,消費者而言都不會有影響;

場景2:

 說明:還是上面的配置,生產者客戶端1 還是連到節點1上,queue1也還是在節點1上, 但是客戶端傳送訊息的時候,採用的路由鍵是key2, 也就是說訊息會被路由到node2上的佇列queue2裡。同理,生產者客戶端2 還是連在節點2上,queue2也還是在節點2上,但是訊息傳送的時候是通過key1路由到nodel1 上的queue1裡。 
複製程式碼

這種場景下出現網路分割槽就有問題了:

出現網路分割槽之後,node1和node2 連不通了,這時候對於生產者客戶端而言:傳送出去的訊息找不到對應的繫結佇列了,訊息會被退回或者丟棄; 對於消費者而言,訊息消費之後,向對應的broker 傳送確認ack訊息的時候,也會發現找不到相應的節點了,這個時候訊息消費端的確認機制也會有問題,可能會收到重複訊息。

個人理解:出現這種問題的根本原因還是在於:rabbitmq的叢集的節點間只是會同步後設資料資訊,訊息只是放在對應的宿主佇列裡。

存在映象佇列的情況:

有映象佇列的情況,複雜的多,因為出現網路分割槽之後,對於映象佇列涉及到主從晉升,這塊的場景後面再進一步詳細分析。

四. rabbitmq 如何應對網路分割槽:

rabbitmq 針對網路分割槽提供了幾種配置:

 [
    {rabbit,
       [
        {tcp_listeners,[5672]},
        {cluster_partition_handling, ignore}
       ]
    }
 ].
複製程式碼

配置項分為以下幾種:

  • ignore 預設型別,不處理。要求你所在的網路環境非常可靠。當出現網路分割槽的時候需要人工介入。

  • pause_minority:
    rabbitmq節點感知叢集中其他節點down掉時,會判斷自己在叢集中處於多數派還是少數派,也就是判斷與自己形成叢集的節點個數在整個叢集中的比例是否超過一半。如果是多數派,則正常工作,如果是少數派,則會停止rabbit應用並不斷檢測直到自己成為多數派的一員後再次啟動rabbit應用。注意:這種處理方式叢集通常由奇數個節點組成。

  • autoheal 你的網路環境可能是不可靠的。你會更加關心服務的可持續性,而非資料完整性。 一般針對包含2個節點的叢集,當網路分割槽恢復後,rabbitmq各分割槽彼此進行協商,分割槽中客戶端連線數最多的為勝者,其餘的全部會進行重啟,恢復到同步狀態。

總結

本文只是簡單介紹了一下rabbitmq的網路分割槽,以及相應的配置策略。由於更多的偏運維層面,實踐經驗較少,可能談的不夠深入,後續在實踐中經過沉澱後再進一步補充。

參考書籍《rabbitmq 實戰》

相關文章