1. 程式人生 > >rabbitMQ集群

rabbitMQ集群

ted spa tro 修改 logs 名稱 partition 故障 位置

配置集群前須知

主機名解析

RabbitMQ節點使用域名相互尋址,因此所有集群成員的主機名必須能夠從所有集群節點解析,可以修改hosts文件或者使用DNS解析

如果要使用節點名稱的完整主機名(RabbitMQ默認為短名稱),並且可以使用DNS解析完整的主機名,則可能需要調查設置環境變量 RABBITMQ_USE_LONGNAME = true

創建集群的方法用多種

  通過配置文件

  rabbitmqctl手動配置

  通過插件(如:AWS(EC2)實例發現,Kubernetes發現,基於Consul的發現,基於etcd的發現)

一個集群的組成可以動態改變,所有的RabbitMQ開始作為單個節點運行,這些節點可以加入到集群,然後也可以再次脫離集群轉回單節點

RabbitMQ集群可以容忍單個節點的故障。節點可以隨意啟動和通知,只要它們可以與在關閉時已知的集群成員節點聯系

集群意味著在局域網使用,不建議運行跨廣域網的集群

節點可以是disk節點或RAM節點

RAM節點將內部數據庫表存儲在RAM中。這不包括消息,消息存儲索引,隊列索引和其他節點狀態
在90%以上的情況下,您希望所有節點都是磁盤節點; RAM節點是一種特殊情況,可用於改善高排隊,交換或綁定流失的性能集群。RAM節點不提供有意義的更高的消息速率。如有疑問,請僅使用磁盤節點
由於RAM節點僅將內部數據庫表存儲在RAM中,因此它們必須在啟動時從對等節點同步它們。這意味著群集必須至少包含一個磁盤節點。因此無法手動刪除集群中剩余的最後一個磁盤節點

rabbitmqctl配置集群

hostname ip system RabbitMQ
rabbit1 192.168.88.1 CentOS7.2.1511 3.7.0
rabbit2 192.168.88.2
rabbit3 192.168.88.3

綁定hosts文件

192.168.88.1 rabbit1
192.168.88.2 rabbit2
192.168.88.3 rabbit3

在三臺機器安裝RabbitMQ

RabbitMQ安裝教程

設置節點互相驗證:Erlang Cookie

RabbitMQ節點和CLI工具(例如rabbitmqctl)使用cookie來確定它們是否被允許相互通信,要使兩個節點能夠通信,它們必須具有相同的共享密鑰,稱為Erlang Cookie.
Cookie只是一個字符串,最多可以有255個字符。它通常存儲在本地文件中。該文件必須只能由所有者訪問(400權限)。每個集群節點必須具有相同的 cookie,文件位置/var/lib/rabbitmq/.erlang.cookie

把rabbit2、rabbit3設置成和rabbit2一樣的即可,權限是400

正常方式啟動所有節點

rabbitmq-server -detached 
rabbitmq-server -detached 
rabbitmq-server -detached

現在啟動了三個獨立的RabbitMQ,我們用cluster_status命令查看集群狀態

[root@rabbit1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1]}]},
 {running_nodes,[rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]}]}]


[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit2">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]}]}]

 
[root@rabbit3 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3]},
 {cluster_name,<<"rabbit@rabbit3">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]}]}]

為了連接集群中的三個節點,我們把rabbit@c2和rabbit@c3節點加入到rabbit@c1節點集群

首先,在rabbit@c1的簇中加入rabbit@c2

  1、停止rabbir@c2的rabbitmq應用程序,

  2、加入rabbit@c1集群

  3、然後啟動RabbitMQ程序

註意:加入集群會隱式重置節點,從而刪除此節點上以前存在的所有資源和數據

[root@rabbit2 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit2 ...

[root@rabbit2 ~]# rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit2 with rabbit@rabbit1

[root@rabbit2 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit2 ...
 completed with 0 plugins.

現在我們在rabbit1、rabbit2任意一個節點上查看集群狀態,我們可以看到這兩個節點加入了一個集群

[root@rabbit1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]

我們再把rabbit3節點加入到這個集群

[root@rabbit3 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit3 ...

[root@rabbit3 ~]# rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit3 with rabbit@rabbit1

[root@rabbit3 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit3 ...
 completed with 0 plugins.

通過任何節點上的cluster_status命令,我們可以看到這三個節點加入了一個集群

[root@rabbit1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]},{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit1,rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]},{rabbit@rabbit1,[]},{rabbit@rabbit2,[]}]}]

[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@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]},{rabbit@rabbit3,[]}]}]

通過遵循上述步驟,我們可以在集群正在運行的同時隨時向集群添加新節點

已加入群集的節點可隨時停止。他們也可以崩潰。在這兩種情況下,群集的其余部分都會繼續運行,並且節點在再次啟動時會自動“跟上”(同步)其他群集節點。

我們關閉rabbit@rabbit1和rabbit@rabbit3,並檢查每一步中的集群狀態

[root@rabbit1 ~]# rabbitmqctl stop
Stopping and halting node rabbit@rabbit1 ...

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]},{rabbit@rabbit2,[]}]}]
 
[root@rabbit3 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit3]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit3,[]}]}]
 
 [root@rabbit3 ~]# rabbitmqctl stop
Stopping and halting node rabbit@rabbit3 ...

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]}]}]

現在我們再次啟動節點,在我們繼續檢查集群狀態時

[root@rabbit3 ~]# rabbitmq-server -detached 
[root@rabbit3 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit3]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit3,[]}]}]

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]},{rabbit@rabbit2,[]}]}]

[root@rabbit1 ~]# rabbitmq-server -detached 
[root@rabbit1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit3,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit3,[]},{rabbit@rabbit1,[]}]}]

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit3,rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit3,[]},{rabbit@rabbit2,[]}]}]

[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@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]},{rabbit@rabbit3,[]}]}]

一些重要的警告:
當整個集群關閉時,最後一個關閉的節點必須是第一個要聯機的節點。
如果要脫機的最後一個節點無法恢復,可以使用forget_cluster_node命令將其從群集中刪除
如果所有集群節點同時停止並且不受控制(例如斷電),則可能會留下所有節點都認為其他節點在其後停止的情況。在這種情況下,您可以在一個節點上使用force_boot命令使其再次可引導

集群移除節點

當節點不再是節點的一部分時,需要從集群中明確地刪除節點。我們首先從集群中刪除rabbit@rabbit3,並將其返回到獨立操作

在rabbit@rabbit3上:

  1、我們停止RabbitMQ應用程序,

  2、重置節點

  3、重新啟動RabbitMQ應用程序

[root@rabbit3 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit3 ...

[root@rabbit3 ~]# rabbitmqctl reset
Resetting node rabbit@rabbit3 ...

[root@rabbit3 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit3 ...
 completed with 0 plugins.

在節點上 運行cluster_status命令確認rabbit@rabbit3現在不再是集群的一部分並獨立運行

[root@rabbit3 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ...
[{nodes,[{disc,[rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3]},
 {cluster_name,<<"rabbit@rabbit3">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit3,[]}]}]
 
[root@rabbit1 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit2,[]},{rabbit@rabbit1,[]}]}]

[root@rabbit2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},{rabbit@rabbit2,[]}]}]

我們也可以遠程刪除節點,例如,在處理無響應的節點時,這很有用
比如:我們在節點rabbit@rabbit2上把rabbit@rabbit1從集群中移除

[root@rabbit1 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit1 ...

[root@rabbit2 ~]# rabbitmqctl forget_cluster_node rabbit@rabbit1
Removing node rabbit@rabbit1 from the cluster

請註意,rabbit1仍然認為它與rabbit2集群 ,並試圖啟動它將導致錯誤。我們需要重新設置才能重新啟動。

[root@rabbit1 ~]# rabbitmqctl reset     #必須要重置
Resetting node rabbit@rabbit1 ...

[root@rabbit1 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit1 ...
 completed with 0 plugins.

現在查看集群狀態,三個節點都時作為獨立的節點

請註意,rabbit@rabbit2保留了簇的剩余狀態,而rabbit@rabbit1 和rabbit@rabbit3是剛剛初始化的RabbitMQ。如果我們想重新初始化rabbit@rabbit2,我們按照與其他節點相同的步驟進行:

[root@rabbit2 ~]# rabbitmqctl stop_app
Stopping rabbit application on node rabbit@rabbit2 ...

[root@rabbit2 ~]# rabbitmqctl reset
Resetting node rabbit@rabbit2 ...

[root@rabbit2 ~]# rabbitmqctl start_app
Starting node rabbit@rabbit2 ...
 completed with 0 plugins.

主機名更改

RabbitMQ節點使用主機名相互通信。因此,所有節點名稱必須能夠解析所有集群對等的名稱。像rabbitmqctl這樣的工具也是如此
除此之外,默認情況下RabbitMQ使用系統的當前主機名來命名數據庫目錄。如果主機名更改,則會創建一個新的空數據庫。為了避免數據丟失,建立一個固定和可解析的主機名至關重要。每當主機名更改時,您應該重新啟動RabbitMQ
如果要使用節點名稱的完整主機名(RabbitMQ默認為短名稱),並且可以使用DNS解析完整的主機名,則可能需要調查設置環境變量 RABBITMQ_USE_LONGNAME = true

從客戶端連接到群集

客戶端可以正常連接到群集中的任何節點。如果該節點出現故障,並且集群的其余部分仍然存在,那麽客戶端應該註意到已關閉的連接,並且應該能夠重新連接到群集的一些幸存的成員。通常,將節點主機名或IP地址燒入客戶端應用程序是不可取的:這會引入不靈活性,並且如果集群配置發生更改或集群中節點數發生更改,則需要編輯,重新編譯和重新部署客戶端應用程序。相反,我們推薦一個更抽象的方法:這可能是一個動態的DNS服務,它具有非常短的TTL配置,或者一個普通的TCP負載均衡器,或者用起搏器或類似技術實現的某種移動IP。一般來說

具有RAM節點的集群

RAM節點只將其元數據保存在內存中。由於RAM節點不必像光盤節點那樣寫入光盤,它們可以更好地執行。但是請註意,由於永久隊列數據總是存儲在磁盤上,因此性能改進將僅影響資源管理(例如添加/刪除隊列,交換或虛擬主機),但不會影響發布速度或消耗速度
RAM節點是高級用例; 設置你的第一個群集時,你應該不使用它們。您應該有足夠的光盤節點來處理您的冗余要求,然後在需要時添加額外的RAM節點進行縮放
只包含RAM節點的集群是脆弱的; 如果群集停止,您將無法再次啟動, 並將丟失所有數據。RabbitMQ將阻止在許多情況下創建RAM節點的群集,但是它不能完全阻止它

這裏的例子僅僅為了簡單起見,顯示了具有一個光盤和一個RAM節點的集群; 這樣的集群是一個糟糕的設計選擇

創建RAM節點
我們可以在首次加入集群時將節點聲明為RAM節點。像之前一樣,我們使用rabbitmqctl join_cluster來完成此 操作,但傳遞 --ram標誌

rabbit2$ rabbitmqctl stop_app
Stopping node rabbit@rabbit2 ...done
.
rabbit2$ rabbitmqctl join_cluster --ram rabbit@rabbit1
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.

RAM節點在集群狀態中顯示為:
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ...
[{nodes,[{disc,[rabbit@rabbit1]},{ram,[rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}]
...done.

rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ...
[{nodes,[{disc,[rabbit@rabbit1]},{ram,[rabbit@rabbit2]}]},
 {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}]
...done.

更改節點類型
我們可以將節點的類型從ram更改為disc,反之亦然。假設我們想要顛倒rabbit @ rabbit2和rabbit @ rabbit1的類型 ,將前者從ram節點轉換為disc節點,將後者從disc節點轉換為ram節點。要做到這一點,我們可以使用 change_cluster_node_type命令。該節點必須先停止

rabbit2$ rabbitmqctl stop_app
Stopping node rabbit@rabbit2 ...done.

rabbit2$ rabbitmqctl change_cluster_node_type disc
Turning rabbit@rabbit2 into a disc node ...
...done.
Starting node rabbit@rabbit2 ...done.

rabbit1$ rabbitmqctl stop_app
Stopping node rabbit@rabbit1 ...done.

rabbit1$ rabbitmqctl change_cluster_node_type ram
Turning rabbit@rabbit1 into a ram node ...

rabbit1$ rabbitmqctl start_app
Starting node rabbit@rabbit1 ...done.

  

rabbitMQ集群