集群文字記錄(Transcript)
下面是通過三臺機器-rabbit1, rabbit2, rabbit3來設置和操作RabbitMQ集群的文字記錄.
我們假設用戶已經登錄到這三臺機器上,并且都已經在機器上安裝了RabbitMQ,以及rabbitmq-server 和rabbitmqctl 腳本都已經在用戶的PATH環境變量中.
This transcript can be modified to run on a single host, as explained more details below.
節點(以及CLI工具)之間如何來認證: Erlang Cookie
RabbitMQ 節點和CLI 工具(如rabbitmqctl) 使用cookie來確定每個節點之間是否可以通信. 兩個節點之間要能通信,它們必須要有相同的共享密鑰Erlang cookie. cookie只是具有字母數字特征的字符串。只要你喜歡,它可長可短. 每個集群節點必須有相同的cookie.
當RabbitMQ 服務器啟動時,Erlang VM 會自動地創建一個隨機的cookie文件. 最簡單的處理方式是允許一個節點來創建文件,然后再將這個文件拷貝到集群的其它節點中。
在 Unix 系統中, cookie的通常位于/var/lib/rabbitmq/.erlang.cookie 或$HOME/.erlang.cookie.
在Windows中, 其位置在C:\Users\Current User\.erlang.cookie(%HOMEDRIVE% + %HOMEPATH%\.erlang.cookie) 或C:\Documents and Settings\Current User\.erlang.cookie, 對于RabbitMQ Windows service其位置在C:\Windows\.erlang.cookie。如果使用了Windows service , cookie可被放于這兩個位置中.
作為替代方案,你可以在 rabbitmq-server 和 rabbitmqctl 腳本中調用erl時,插入"-setcookie cookie"選項.
當cookie未配置時 (例如,不相同), RabbitMQ 會記錄這樣的錯誤"Connection attempt from disallowed node" and "Could not auto-cluster".
啟動獨立節點
集群可通過重新配置,而將現有RabbitMQ 節點加入到集群配置中. 因此第一步是以正常的方式在所有節點上啟動RabbitMQ:
rabbit1$ rabbitmq-server -detached
rabbit2$ rabbitmq-server -detached
rabbit3$ rabbitmq-server -detached
這會創建三個獨立的RabbitMQ brokers, 每個節點一個,可通過cluster_status命令來驗證:
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1]}]},{running_nodes,[rabbit@rabbit1]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit2]}]},{running_nodes,[rabbit@rabbit2]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}] ...done.
以rabbitmq-server shell腳本來啟動RabbitMQ broker的節點名稱是rabbit@shorthostname,在這里,短節點名稱是小寫的(如上面的rabbit@rabbit1). 如果在windows上,你使用rabbitmq-server.bat批處理文件來啟動,短節點名稱是大寫的(如:rabbit@RABBIT1). 當你輸入節點名稱時,不論是大寫還是小寫的,這些字符串都必須精確匹配。
創建集群
為了把這三個節點構建到一個集群中,我們可以告訴其中的兩個節點, 假設為rabbit@rabbit2 和 rabbit@rabbit3, 將加入到第三個節點的集群中,這第三個節點假設為rabbit@rabbit1.
首先我們將rabbit@rabbit2加入到rabbit@rabbit1的集群中. 要做到這一點,我們必須在rabbit@rabbit2 上停止RabbitMQ應用程序,并將其加入到rabbit@rabbit1 集群中, 然后再重啟RabbitMQ 應用程序.
注意:加入集群會隱式地重置節點, 因此這會刪除此節點上先前存在的所有資源和數據.(如何備份數據)
rabbit2$ rabbitmqctl stop_app
Stopping node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl join_cluster rabbit@rabbit1
Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.
在每個節點上通過運行cluster_status 命令,我們可以看到兩個節點已經加入了集群:
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]}, {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}] ...done.
現在我們將rabbit@rabbit3節點加入到同一個集群中. 操作步驟同上面的一致,除了這次我們選擇rabbit2來加入集群,但這并不重要:
rabbit3$ rabbitmqctl stop_app
Stopping node rabbit@rabbit3 ...done.
rabbit3$ rabbitmqctl join_cluster rabbit@rabbit2
Clustering node rabbit@rabbit3 with rabbit@rabbit2 ...done.
rabbit3$ rabbitmqctl start_app
Starting node rabbit@rabbit3 ...done.
在任何一個節點上通過運行cluster_status命令,我們可以看到三個節點已經加入了集群:
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]}] ...done.
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]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1,rabbit@rabbit3]}] ...done.
通過上面的步驟,當集群運行的時候,我們可以在任何時候將新的節點加入到集群中.
重啟集群節點
注意,加入到集群中的節點可在任何時候停止, 對于崩潰來說也沒有問題. 在這兩種情況下,集群剩余的節點將不受影響地繼續操作,當它們重啟的時候,這些崩潰的節點會再次自動追趕上其它的集群節點。
我們關閉了節點rabbit@rabbit1和rabbit@rabbit3,并在每步觀察集群的狀態:
rabbit1$ rabbitmqctl stop
Stopping and halting node rabbit@rabbit1 ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit3,rabbit@rabbit2]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit3]}] ...done.
rabbit3$ rabbitmqctl stop
Stopping and halting node rabbit@rabbit3 ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit2]}] ...done.
譯者注:關閉了rabbit1節點后,運行的節點已經沒有rabbit1節點了
現在我們再次啟動節點,并檢查集群狀態:
rabbit1$ rabbitmq-server -detached
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}] ...done.
rabbit3$ rabbitmq-server -detached
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1,rabbit@rabbit3]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1,rabbit@rabbit3]}] ...done.
這里有一些重要的警告:
- 當整個集群崩潰的時候, 最后一個崩潰的節點必須第一個上線.如果不是這樣,節點將會等待最后一個磁盤節點30秒以確認其重新上線,否則就會失敗. 如果最后一個下線的節點,不能再重新上線,那么它可能會使用forget_cluster_node命令來從集群中刪除 - 查閱 rabbitmqctl頁面來了解更多信息.
- 如果所有集群節點都在同一個時間內停止且不受控制(如斷電)。在這種情況下,你可以在某個節點上使用force_boot命令使其再次成為可啟動的-查閱 rabbitmqctl頁面來了解更多信息.
脫離集群
當節點不再是集群的一部分時,可以明確地將其從集群中刪除. 首先我們將節點rabbit@rabbit3從集群中刪除, 以使其回歸獨立操作.要做到這一點,需要在rabbit@rabbit3節點上停止RabbitMQ 應用程序,重設節點,并重啟RabbitMQ應用程序.
rabbit3$ rabbitmqctl stop_app
Stopping node rabbit@rabbit3 ...done.
rabbit3$ rabbitmqctl reset
Resetting node rabbit@rabbit3 ...done.
rabbit3$ rabbitmqctl start_app
Starting node rabbit@rabbit3 ...done.
在節點上運行cluster_status 命令來確認rabbit@rabbit3節點現在已不再是集群的一部分,并且會獨自操作:
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]}, {running_nodes,[rabbit@rabbit2,rabbit@rabbit1]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]}, {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}] ...done.
我們也可以遠程地刪除節點,這是相當有用的,舉例來說,當處理無反應的節點時.舉例來說,我們可以從 rabbit@rabbit2中刪除rabbit@rabbi1.
rabbit1$ rabbitmqctl stop_app
Stopping node rabbit@rabbit1 ...done.
rabbit2$ rabbitmqctl forget_cluster_node rabbit@rabbit1
Removing node rabbit@rabbit1 from cluster ... ...done.
注意,rabbit1仍然認為它與rabbit2處在一個集群中,但嘗試啟動時會出現一個錯誤.這時,我們需要對其進行重置以使其能再次啟動.
rabbit1$ rabbitmqctl start_app
Starting node rabbit@rabbit1 ... Error: inconsistent_cluster: Node rabbit@rabbit1 thinks it's clustered with node rabbit@rabbit2, but rabbit@rabbit2 disagrees
rabbit1$ rabbitmqctl reset
Resetting node rabbit@rabbit1 ...done.
rabbit1$ rabbitmqctl start_app Starting node rabbit@mcnulty ... ...done.
現在, cluster_status 命令會顯示三個節點都是獨立節點,并且操作是獨立的:
rabbit1$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit1 ... [{nodes,[{disc,[rabbit@rabbit1]}]},{running_nodes,[rabbit@rabbit1]}] ...done.
rabbit2$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit2 ... [{nodes,[{disc,[rabbit@rabbit2]}]},{running_nodes,[rabbit@rabbit2]}] ...done.
rabbit3$ rabbitmqctl cluster_status
Cluster status of node rabbit@rabbit3 ... [{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}] ...done.
注意:rabbit@rabbit2節點仍然殘留有集群的狀態(譯者注:怎么看出來的呢?), 但是 rabbit@rabbit1 和rabbit@rabbit3 節點是新鮮的RabbitMQ brokers.如果我們想重新初始化rabbit@rabbit2節點,我們可以按其它節點的步驟來操作:
rabbit2$ rabbitmqctl stop_app
Stopping node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl reset
Resetting node rabbit@rabbit2 ...done.
rabbit2$ rabbitmqctl start_app
Starting node rabbit@rabbit2 ...done.
單臺機器上的集群
在某些情況下,在一臺機器上運行RabbitMQ節點的集群是有用的(試驗性質).
要在一臺機器上運行多個RabbitMQ節點,必須確保節點含有不同的節點名稱,數據存儲路徑,日志文件位置,綁定到不同的端口,并包含那些插件使用的端口等等 .參考配置指南中的RABBITMQ_NODENAME, RABBITMQ_NODE_PORT, 和 RABBITMQ_DIST_PORT文檔 ,以及 File and Directory Locations guide指南中的 RABBITMQ_MNESIA_DIR, RABBITMQ_CONFIG_FILE, and RABBITMQ_LOG_BASE。
你可以在同一個主機上通過重復調用rabbitmq-server(rabbitmq-server.bat on Windows)來手動地啟動多個節點 . 例如:
$ RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit rabbitmq-server -detached
$ RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=hare rabbitmq-server -detached
$ rabbitmqctl -n hare stop_app
$ rabbitmqctl -n hare join_cluster rabbit@`hostname -s`
$ rabbitmqctl -n hare start_app
這會設置兩個節點的集群,這兩個節點都是磁盤節點. 注意,如果你想打開非AMQP的其它端口,你需要通過命令行進行配置:
$ RABBITMQ_NODE_PORT=5672 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15672}]" RABBITMQ_NODENAME=rabbit rabbitmq-server -detached
$ RABBITMQ_NODE_PORT=5673 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME=hare rabbitmq-server -detached
內存節點集群
內存節點只在內存中保存其元數據。它不會像磁盤節點將元數據寫入到磁盤中,但它們擁有更好的性能。 然而,也應該注意到,由于持久化隊列數據總是存儲在磁盤上的,其性能提升只會影響資源管理(如: 添加/刪除隊列,交換機,或虛擬主機), 但不會影響發布或消費的速度.
內存節點是一個高級使用例子;當設置你的第一個集群時,你應該不使用它們。你應該用足夠的磁盤節點來處理冗余需求,然后如果有必要,再用內存節點進行擴展.
集群中只含有內存節點是相當脆弱的,如果集群停止了,你將不能再次啟動,并且會導致數據丟失。RabbitMQ在許多情況下,會阻止創建只包含內存節點的集群,但不能完全阻止。
(譯者注:在集群構建中,最好有兩個或以上的磁盤節點,然后再考慮使用內存節點進行擴展)
創建內存節點
當節點加入集群時,我們可將其聲明為內存節點. 我們可以通過使用像先前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.
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.
改變節點類型
我們可以將節點的類型從磁盤修改為內存,反之亦然. 假設我們想反轉rabbit@rabbit2 和 rabbit@rabbit1的節點類型,即先將內存節點轉換為磁盤節點,隨后再將其從磁盤節點轉換為內存節點.要做到這點,我們可以使用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.