RabbitMQ上手記錄–part 4-節點集羣(單機多節點)

  如今互聯網應用動不動就說要HA,好像不搞個HA都很差意思說本身的應用能承載高併發,大用戶量訪問。RabbitMQ這個經典的消息組件,也必然逃不掉單點失效的尷尬局面。固然在RabbitMQ在被普遍應用於互聯網以後,就對這個HA的需求作了實現,提供了集羣供。這是RabbitMQ的內置功能,就跟普通集羣的做用同樣,就是在某個節點發生異常時,讓生產者和消費者能保持通信狀態,同時經過提供更多的節點來增長系統的吞吐量。node

 

RabbitMQ集羣簡介服務器

RabbitMQ的集羣實現是基於OTP分佈式通信框架實現的,該框架由Erlang語言實現。當一個節點失效的時候,客戶端會自動鏈接到集羣裏的另外一個節點,整個過程調用方不受影響,就好像沒有斷開同樣。同時當集羣承受加大的訪問量的時候,能夠經過添加更多的節點,線性的增長吞吐量和提升性能。可是RabbitMQ集羣不能保證消息不丟失(這是另一個話題了)。架構

RabbitMQ的集羣僅僅是增長節點,可是節點之間的隊列數據是不會同步的,也就是各個節點有本身獨立的隊列數據。這是RabbitMQ的默認設置。因此並非說實現了集羣,就能夠保證數據的一致,這點須要明確。併發

 

RabbitMQ的集羣架構簡介app

1.元數據(metadata)框架

元數據是RabbitMQ跟蹤節點、提供連接信息的基本數據信息。分佈式

這裏的元數據包含如下內容高併發

隊列元數據:隊列名稱和屬性(好比是否持久隊列或者是否自動刪除隊列)性能

Exchange元數據:Exchange名稱,類型以及屬性spa

綁定元數據(Binding):能夠理解爲一個路由表,就是如何經過Exchange找到消息隊列,將消息投到隊列。

Vhost元數據:命令空間、隊列、Exchange的權限信息以及vhost內部的綁定信息。

 

有了這些metadata,RabbitMQ就能跟蹤節點的所在服務器、節點之間的關係以及其餘跟蹤信息。metadata能夠保存在內存或者磁盤中。保存在磁盤的話,那麼在重啓RabbitMQ節點以後就能重建隊列和exchange。

 

集羣節點中的隊列

在上面介紹集羣的時候,提到了一個關鍵的點,就是隊列數據只存在於本地節點,不會同步到各個節點。在一個集羣裏面,建立一個隊列時,只會在本地節點建立隊列信息。這樣只有本地節點知道隊列的全部信息,因此一旦這個節點失效了,這個隊列和對應的綁定信息也會消失。對於消費者來講,就失去了訂閱信息,新生成的消息也沒法投遞,因爲投遞到了黑洞。

 

理論上看起來能夠經過metadata去恢復隊列信息,可是若是在其餘非失效節點恢復隊列信息,那麼會出現404錯誤。這樣作的目的是確保消息只存在於失效的隊列中。咱們惟一能作的就是恢復失效的節點。(以上問題只存在於支持持久的隊列,若是隊列不是持久的,能夠直接恢復,反正沒有數據須要處理)。

 

那麼RabbitMQ爲何不把隊列數據同步到各個節點呢?有如下2個緣由:

1.存儲空間問題

若是每一個節點都包含了隊列信息,會致使多出N倍的數據存儲空間。

2 性能問題

對應支持持久的消息隊列,保存到每一個節點中須要不少IO寫入和帶寬,從而影響整個集羣的性能。

 

集羣中的Exchange

整個正好跟消息隊列相反,Exchange的信息是分佈式的,也就是各個節點都具備一份完整的Exchange信息。實際上Exchange就是一個路由表,因此很容易將路由信息複製到各個節點。

 

image(集羣中的queue和Exchange結構圖,來自《RabbitMQ In Action》

 

 

集羣節點類型

最後一部分理論,講完就進入啪啪的敲代碼實際操做。

RabbitMQ的集羣根據存儲類型能夠分紅兩種類型:內存節點和磁盤節點。這裏存儲的是metadata,內存節點保存在內存中,磁盤節點保存在磁盤中。

若是隻有一個節點(或者說是單節點),只能是磁盤節點,不然RabbitMQ重啓以後就啥也找不回了。

若是至少有一個磁盤節點,那麼其餘節點能夠定義成內存節點。存儲在內存節點的好處固然是爲了提升訪問速度。而磁盤節當然重要,也不是越多越好。由於每次變動metadata數據的時候,都須要將數據寫入到磁盤節點,那麼這個寫入會拖慢集羣的訪問效率。

因此至少保持一個磁盤節點,那麼一旦重啓或者恢復,其餘節點也能正常恢復metadata數據。

 

好了理論講了半天,本身都以爲囉嗦,詳細的內容仍是看文檔吧。

 

練習在本機搭建集羣節點

這個集羣不必定是要在多個服務器跑多個節點,一個服務器上也能夠運行多個節點,能夠理解爲多個進程監聽不一樣的端口號,而且節點的名稱不一樣。我這裏演示的是在一個服務器上運行多個節點。

 

僅僅是搭建集羣節點命令很簡單

1.首先確認安裝好了RabbitMQ,而後中止默認啓動的那個節點

sudo rabbitmqctl stop_app

sudo rabbitmqctl stop

2.而後依次執行如下三個命令,其實是建立了三個節點,不一樣的端口號和節點名稱

sudo RABBITMQ_NODENAME=rabbit RABBITMQ_NODE_PORT=5672 rabbitmq-server -detached
sudo RABBITMQ_NODENAME=rabbit_1 RABBITMQ_NODE_PORT=5673 rabbitmq-server -detached
sudo RABBITMQ_NODENAME=rabbit_2 RABBITMQ_NODE_PORT=5674 rabbitmq-server –detached

這裏使用了兩個環境變量,分別是RABBITMQ_NODENAMERABBITMQ_NODE_PORT,也就是定義了節點名稱和節點的監聽端口號。

運行成功以後,就應該有三個節點在運行,可依次執行如下命令驗證

sudo rabbitmqctl -n rabbit@bogon status

sudo rabbitmqctl -n rabbit_1@bogon status

sudo rabbitmqctl -n rabbit_2@bogon status

這裏運行rabbitmqctl時指定了節點的名稱-n,格式爲:節點名@主機名, bogon是個人主機名,要根據實際狀況修改。

3.造成集羣

目前爲止有三個節點,可是這三個節點是獨立運行的,沒有任何關聯,下面來創建集羣關係。

咱們以第一個節點爲metadata的提供節點,其餘2個節點做爲集羣節點加入,也就是第2和第3個節點要獲得第一個節點的metadata信息。

 

首先中止節點2

sudo rabbitmqctl -n rabbit_1@bogon stop_app

 

重置節點2的metadata

sudo rabbitmqctl -n rabbit_1@bogon reset

 

將節點2加入到節點1中

sudo rabbitmqctl -n rabbit_1@bogon join_cluster rabbit@bogon

(這裏加入節點後,節點2將做爲磁盤節點)

 

啓動節點2

sudo rabbitmqctl -n rabbit_1@bogon start_app

 

查看節點2的集羣狀態

sudo rabbitmqctl -n rabbit_1@bogon cluster_status

輸出以下信息

[{nodes,[{disc,[rabbit@bogon,rabbit_1@bogon]}]},
  {running_nodes,[rabbit@bogon,rabbit_1@bogon]},

能夠看到目前有兩個節點,都是磁盤類型的節點,而且都在運行

 

繼續加入節點3,前兩部中止和重置同樣,只是改個節點名稱

sudo rabbitmqctl -n rabbit_2@bogon stop_app

sudo rabbitmqctl -n rabbit_2@bogon reset

 

將節點3加入到節點1,可是設置節點3位內存節點,注意最後的--ram參數

sudo rabbitmqctl -n rabbit_2@bogon join_cluster rabbit@bogon –ram

 

啓動節點3並查看集羣狀態

sudo rabbitmqctl -n rabbit_2@bogon start_app

sudo rabbitmqctl -n rabbit_2@bogon cluster_status

輸出信息以下

[{nodes,[{disc,[rabbit_1@bogon,rabbit@bogon]},{ram,[rabbit_2@bogon]}]},
  {running_nodes,[rabbit@bogon,rabbit_1@bogon,rabbit_2@bogon]},

能夠看到目前有三個節點,第三個節點是內存節點。

 

好了,到目前爲此單機多節點就搭建完了,那有什麼用呢?上述顯示的running_nodes都是能夠被鏈接的,最起碼增長了鏈接數,也有個最起碼的概念,接下來會整理如何將節點分佈運行在不一樣的服務器。

相關文章
相關標籤/搜索