rabbitMQ集群
配置集群前須知
主機名解析
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
正常方式啟動所有節點
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集群