爲了使得 RabbitMQ 可以達到高可用,需要允許消費者和生產者在 RabbitMQ 節點崩潰的情況下可以繼續工作,所以一般線上部署的都會是集羣。因爲在自己的電腦上部署集羣,沒有那麼多的機器,部署真正的多機多實例的情況;所以就有了這篇,單機多 RabbitMQ 實例集羣的搭建。
基礎概念
RAM node:內存節點將所有的隊列、交換機、綁定、用戶、權限和 vhost 的元數據存儲在內存,這樣可以使像交換機、隊列聲明等操作更加迅速。
Disk node:將元數據存儲在磁盤,單節點系統只允許磁盤類型的節點,可以防止重啓 RabbitMQ 實例的時候,丟失配置的信息。
注:RabbitMQ 集羣中至少要有一個磁盤節點,所有其他節點可以是內存節點,當節點加入或者離開集羣時,必須將本次變更通知到至少一個磁盤節點。如果集羣中唯一的磁盤節點崩潰,集羣仍然可以運行,只是無法進行增刪改查操作,只有唯一的磁盤節點節點恢復以後,纔可以繼續進行增刪改查。爲了避免這種情況,可以設置兩個磁盤節點,保證了至少有一個是磁盤節點,從而可以保存元數據的更改。
集羣模式
RabbitMQ 的集羣模式一般分爲兩種,普通模式 和 鏡像模式。
普通模式:默認的集羣模式,以兩個節點(rabbit1、rabbit2)爲例說明。消息實體只存在其中一個節點 rabbit1 或者 rabbit2,rabbit1 和 rabbit2 兩個節點僅有相同的元數據,就是隊列的結構。當消息進入 rabbit1 節點的隊列(Queue)後,當消費者從 rabbit2 節點消費時,集羣會臨時在 rabbit1 和 rabbit2 節點間傳遞消息,把 rabbit1 節點下隊列的消息實體取出,然後通過 rabbit2 發送給消費者。所以消費者需要儘量連接每一個節點,同時,需要將同一個邏輯隊列,在多個節點都建立。不然消費者連 rabbit1 或 rabbit2 節點,出口卻只有 rabbit1,而且當 rabbit1 節點故障後,rabbit2 節點無法取到 rabbit1 節點中還未消費的消息。如果做了消息持久化,還可以等 rabbit1 節點恢復後繼續消費;如果沒有持久化就會消息丟失消息。
鏡像模式:將隊列變爲鏡像隊列,存在於多個節點。消息實體會主動在節點之間同步,不會像普通模式,在消費者消費數據時才臨時讀取。缺點 —— 集羣內部的同步會佔用大量帶寬。
配置普通模式的集羣
1、配置系統配置信息,支持單機多實例
普通集羣,是從單機形式演變過來的,所以要基於之前的文章《Windows 下搭建 RabbitMQ 環境》,進行相關的配置。
爲了使得單臺機器可以運行多個 RabbitMQ 實例,我們需要修改一下 hosts 文件,一般情況下 hosts 文件的路徑都是 C:\Windows\System32\drivers\etc,增加如圖所示的配置信息
其中節點名 rabbit-node1 和 rabbit-node2 後面會用到
127.0.0.1 rabbit-node1
127.0.0.1 rabbit-node2
爲了使用方便,在《Windows 下搭建 RabbitMQ 環境》中配置了 RabbitMQ 的環境變量,爲了更清晰的表現出來啓動的是哪一個節點的 RabbitMQ 實例,這裏最好是刪除這個環境變量的設置。
將之前 rabbitmq_server-3.7.7(單機版本的唯一節點實例)的文件複製一份,作爲集羣下的另外一個節點的 rabbitmq_server-3.7.7-node1 來運行。
2、配置集羣內的 rabbit-node1 節點
修改 D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7\sbin(根據實際安裝路徑調整)下的 rabbitmq-env.bat 的文件內容,增加如下信息
set RABBITMQ_CONFIG_FILE=!RABBITMQ_HOME!\etc\rabbitmq-node1
set RABBITMQ_BASE=!RABBITMQ_BASE!\rabbitmq-cluster
set RABBITMQ_NODENAME=rabbit1@rabbit-node1
set RABBITMQ_NODE_PORT=5672
其中 set RABBITMQ_NODENAME=rabbit1@rabbit-node1 的 rabbit-node1 需要與 host 中配置的一致。同時這裏面 RABBITMQ_CONFIG_FILE 依賴了 rabbitmq-node1 文件,說明需要一個 rabbitmq-node1 的配置文件,這個文件應該在 D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7\etc (根據實際的安裝路徑調整)路徑下,如果沒有,可以把 rabbitmq.config.example 文件複製一份,並命名 rabbitmq-node1.config 即可。
爲 rabbitmq-node1.config 調整一下監聽的配置,新增如下內容
{listener, [{port, 15672},
{ip, "127.0.0.1"},
{ssl, false}
]}
到此 rabbit-node1 節點的配置基本完成,此時,需要開啓 rabbit-node1 節點,進入 rabbit-node1 節點的安裝路徑(可以使用 cd /d 命令),運行啓動命令 rabbitmq-server.bat,如下所示
cd /d D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7\sbin
rabbitmq-server.bat
出現類似下圖的打印信息後,說明 rabbit-node1 啓動成功
再打開一個 DOS 終端,進入 sbin 目錄,啓用 rabbitmq-plugins 插件
rabbitmq-plugins.bat enable rabbitmq_management
如果一切配置順利,就可以使用瀏覽器登錄 http://localhost:15672
看起來好像和單機單實例沒什麼區別,但是還沒完,因爲配置的是集羣,還要繼續配置 rabbit-node2 節點。
2、配置集羣內的 rabbit-node2 節點
rabbit-node2 節點的配置和 rabbit-node1 節點的類似。
修改 D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7-node1\sbin(根據實際安裝路徑調整)下的 rabbitmq-env.bat 的文件內容,增加如下信息
set RABBITMQ_CONFIG_FILE=!RABBITMQ_HOME!\etc\rabbitmq-node2
set RABBITMQ_BASE=!RABBITMQ_BASE!\rabbitmq-cluster
set RABBITMQ_NODENAME=rabbit2@rabbit-node2
set RABBITMQ_NODE_PORT=5673
在 rabbit-node2 的配置裏面要注意一點 set RABBITMQ_NODENAME=rabbit2@rabbit-node2 節點名稱需要與 rabbit-node1 的區分開,這裏是 rabbit2 而 rabbit-node1 裏面配置的 rabbit1,如果沒有區分,rabbit-node2 是無法啓動的,會提示如下的錯誤
同樣在對應的 etc(示例的是 D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7-node1\etc) 路徑下需要一個 rabbitmq-node2.config 的配置文件
這裏監聽的端口需要與 rabbit-node1 節點的區分開來,所以使用的 15673
{listener, [{port, 15673},
{ip, "127.0.0.1"},
{ssl, false}
]}
至此,rabbit-node2 節點也配置完成了,我們需要啓動一下 rabbit-node2 節點,進入 rabbit-node2 節點的安裝路徑,運行啓動命令 rabbitmq-server.bat,如下所示
cd /d D:\software\rabbitmq-server-windows-3.7.7\rabbitmq_server-3.7.7-node1\sbin
rabbitmq-server.bat
出現如下圖所示的打印,說明 rabbit-node2 節點也啓動完成
同樣的,再打開一個 DOS 終端,進入 sbin 目錄,啓用 rabbitmq-plugins 插件
rabbitmq-plugins.bat enable rabbitmq_management
順利的話,就能使用瀏覽器登錄 http://localhost:15673
3、配置集羣
到現在,只是在單機上運行了兩個 RabbitMQ 的實例,還需要繼續配置集羣。
本文示例是對 rabbit-node2 節點的配置,進入 rabbit-node2 節點的 sbin 目錄下操作。
rabbitmqctl.bat stop_app
rabbitmqctl.bat join_cluster rabbit1@rabbit-node1
rabbitmqctl.bat start_app
普通模式下的集羣配置完成了,查看一下,配置是否成功
rabbitmqctl.bat cluster_status
出現類似如下的截圖,說明集羣配置已經完成。
從瀏覽器中查看,出現如下的截圖,說明配置完成。
注:這個時候的集羣還不具有高可用,當我們在 springboot 項目裏配置了這個集羣的時候,手動關閉 rabbit-node1 節點,我們的項目就不能繼續收發消息了。原因已經在集羣模式一段中介紹了。
配置鏡像模式的集羣
鏡像模式是基於普通模式的配置,所以沒有把鏡像模式單獨列出來一章來講述,接下來看看怎麼配置吧。
在 Admin 分頁下,點擊 Policies 選項,添加新的策略
新策略可以按照截圖中配置。
Name:策略的名稱,自行定義。
Pattern:匹配規則,這裏是爲所有隊列鏡像,使用的是 .* 。
Apply to:適用於什麼對象,可以選擇,示例選擇的是交換器和隊列。
Definition:需要配置 ha-mode 和 ha-sync-mode
ha-mode 提供了三種模式:
all:全部的節點隊列都做鏡像 --- 示例的配置項
exactly:指定鏡像隊列的節點上限數量
nodes:只爲指定節點配置鏡像隊列
ha-sync-mode 提供了兩種模式:
automatic:自動 --- 示例的配置項
manual:手動
配置完成後,點擊 Add policy
如果新策略添加成功,如有如截圖中的內容。
到現在,RabbitMQ 集羣的鏡像模式配置完成了。
測試鏡像模式的集羣
要測試 RabbitMQ 集羣的高可用,需要使用之前的 Springboot 項目,使 Springboot 項目依賴這個 RabbitMQ 集羣。
因爲依賴的是集羣,所以不再是是使用單個 RabbitMQ 實例的地址和端口。
spring.rabbitmq.addresses=127.0.0.1:5672, 127.0.0.1:5673
先看看,我們的集羣,使用的是哪個節點的哪個隊列
再來看看測試代碼的實現
當集羣的兩個節點都在運行的時候,做一次發送
這個時候可以收到消息
現在關閉一個節點測試一下,把 rabbit-node1 節點關掉
先看看現在集羣使用的隊列
再發一次消息
還是可以正常的收發消息。