普通叢集:多個節點組成的普通叢集,訊息隨機傳送到其中一個節點的佇列上,其他節點僅保留後設資料,各個節點僅有相同的後設資料,即佇列結構、交換器結構、vhost等。消費者消費訊息時,會從各個節點拉取訊息,如果儲存訊息的節點故障,則無法消費訊息,如果做了訊息持久化,那麼得等該節點恢復,然後才可被消費;如果沒有持久化的話,就會產生訊息丟失的現象。
映象叢集:它是在普通模式的基礎上,把需要的佇列做成映象佇列,存在於多個節點來實現高可用(HA)。該模式解決了上述問題,Broker會主動地將訊息實體在各映象節點間同步,在consumer取資料時無需臨時拉取。該模式帶來的副作用也很明顯,除了降低系統效能外,如果映象佇列數量過多,加之大量的訊息進入,叢集內部的網路頻寬將會被大量消耗。通常地,對可靠性要求較高的場景建議採用映象模式。
一、搭建RabbitMq的執行環境
我本機是window10,通過docker搭建兩個rabbitmq節點。
1.通過search查詢rabbitmq映象
docker search rabbitmq
2.通過pull拉取rabbitmq的官方最新映象
這裡最好帶上tag為management的版本,否則拉最新的latest,web管理頁無法顯示全,會提示overview:management only mode
docker pull rabbitmq:3.8.25-management
3.建立容器
docker run -d --name rabbitmq1 -p 5672:5672 -p 15672:15672 --hostname myRabbit1 -e RABBITMQ_DEFAULT_VHOST=my_vhost1 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin a4eb038c2ecb
--name:容器名稱
-p:端點對映
--hostname:rabbitmq的節點名稱
-e RABBITMQ_DEFAULT_VHOST:虛擬主機名稱
-e RABBITMQ_DEFAULT_USER:登入賬號
-e RABBITMQ_DEFAULT_PASS:登入密碼
a4eb038c2ecb是映象id,根據自己情況替換。
4.啟動管理頁面
我們的映象預設沒有開啟web管理頁面,所以我們通過exec命令進入容器啟動,這個映象的環境是ubuntu的
PS C:\> docker exec -it 639a151c5440 /bin/bash
root@myRabbit:/# rabbitmq-plugins enable rabbitmq_management
瀏覽器中訪問http://localhost:15672/即可開啟,另一個rabbitmq如法炮製,區別之處在於更換埠為5673和15673等,並且建立容器時使用--link連線第一個rabbitmq節點(也可建立橋接網路network連線),如下
docker run -d --name rabbitmq2 -p 5673:5672 -p 15673:15672 --hostname myRabbit2 -e RABBITMQ_DEFAULT_VHOST=my_vhost2 -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin --link rabbitmq1:myRabbit1 a4eb038c2ecb
5.設定erlang cookie
erlang cookie原本可以通過run容器時設定引數-e RABBITMQ_ERLANG_COOKIE,但是現在過期棄用了。
我們先通過docker logs命令檢視容器的執行日誌,尋找home dir引數如下
PS D:\> docker logs rabbitmq1 //.....這裡省略 Starting broker...2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> node : rabbit@myRabbit1 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> home dir : /var/lib/rabbitmq 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> config file(s) : /etc/rabbitmq/conf.d/10-default-guest-user.conf 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> : /etc/rabbitmq/conf.d/management_agent.disable_metrics_collector.conf 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> cookie hash : Aed9pjd9vYWw3hng7Gjmkg== 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> log(s) : /var/log/rabbitmq/rabbit@myRabbit1_upgrade.log 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> : <stdout> 2021-11-17 02:19:55.859245+00:00 [info] <0.222.0> database dir : /var/lib/rabbitmq/mnesia/rabbit@myRabbit1
所以.erlang.cookie檔案在此路徑下,我們進入容器可以看到此檔案
root@myRabbit1:~# ls -a /var/lib/rabbitmq . .. .bash_history .erlang.cookie mnesia
我們再設定erlang cookie的許可權,在容器內執行如下程式碼,如果許可權不夠後續操作會報錯
chmod 600 /var/lib/rabbitmq/.erlang.cookie
之後我們通過docker cp命令將rabbitmq1中的.erlang.cookie檔案拷到物理機上再拷貝到rabbitmq2的容器中,物理機和容器之間複製命令如下:
- 容器複製檔案到物理機:docker cp 容器名稱:容器目錄 物理機目錄
- 物理機複製檔案到容器:docker cp 物理機目錄 容器名稱:容器目錄
具體程式碼如下:
docker cp rabbitmq1:/var/lib/rabbitmq/ d:\workspace\
docker cp d:\workspace\rabbitmq\.erlang.cookie rabbitmq2:/var/lib/rabbitmq/
複製之後需要重啟rabbitmq2容器,否則執行rabbitmqctl命令報如下錯誤:
[error] Cookie file /var/lib/rabbitmq/.erlang.cookie must be accessible by owner only
二、普通模式
重啟後進入容器將rabbitmq2的節點加入rabbitmq1中建立普通叢集,分別執行如下程式碼即可:
rabbitmqctl stop_app rabbitmqctl reset rabbitmqctl join_cluster --ram rabbit@myRabbit1 //myRabbitmq1為rabbitmq1容器中rabbitmq的hostname rabbitmqctl start_app
之後我們再web管理頁可以看到兩個節點了。
在任意一個節點建立一個佇列,另一個節點也會生成相同的佇列。而且可以發現rabbitmq2的vhost從my_vhost2變為了my_vhost1與rabbitmq相同了。
三、映象模式
映象模式就是在普通模式的基礎上進入rabbitmq1容器輸入如下命令即可:
rabbitmqctl set_policy -p my_vhost1 ha-all "^" '{"ha-mode":"all"}' --apply-to all
具體的格式為
rabbitmqctl set_policy [-p Vhost] Name Pattern Definition [Priority] -p Vhost: 可選引數,針對指定vhost下的queue進行設定 Name: policy的名稱 Pattern: queue的匹配模式(正規表示式) Definition:映象定義,包括三個部分ha-mode, ha-params, ha-sync-mode ha-mode:指明映象佇列的模式,有效值為 all/exactly/nodes all:表示在叢集中所有的節點上進行映象 exactly:表示在指定個數的節點上進行映象,節點的個數由ha-params指定 nodes:表示在指定的節點上進行映象,節點名稱通過ha-params指定 ha-params:作為引數,為ha-mode的補充 ha-sync-mode:進行佇列中訊息的同步方式,有效值為automatic和manual priority:可選引數,policy的優先順序 rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}' --apply-to all
或者登入rabbitmq管理頁面 ——> Admin ——> Policies ——> Add / update a policy
name:策略名稱
Pattern:^ 匹配符,只有一個^代表匹配所有。^message指同步“message”開頭的佇列名稱
Definition:ha-mode=all 為匹配型別,分為3種模式:all(表示所有的queue)
Priority:優先順序,首先根據priority
排序,值越大的優先順序越高;相同priority
則根據建立時間排序,越晚建立的優先順序越高。
簡單說明一下 Operator Policy 和 User Policy 的區別:
- Operator Policy 是給服務提供商或公司基礎設施部門用來設定某些需要強制執行的通用規則
- User Policy 是給業務應用用來設定的規則
Operator Policy 和 User Policy 會合並後作用於佇列,並且為防止 Operator Policy 對佇列某些關鍵屬性例如死信佇列交換器Dead Letter Exchange
的覆蓋導致業務應用產生非預期的結果,Operator Policy 只支援 expire
、message-ttl
、max-length
、max-length-bytes
4個引數。
參考學習:
https://www.cnblogs.com/knowledgesea/p/6535766.html
https://blog.csdn.net/belonghuang157405/article/details/83540148