Rabbitmq 相關介紹之單機集群配置
一、說明:
說到集群,大家應該都不陌生,為了提高性能需要配置集群,而在有的時候,我們需要在測試環境先測試然後灰度上線,所以這裏介紹在一臺服務器上配置rabbitmq集群
二、rabbitmq集群模式
1、普通模式:rabbitmq默認的集群模式
RabbitMQ集群中節點包括內存節點、磁盤節點。內存節點就是將所有數據放在內存,磁盤節點將數據放在磁盤上。如果在投遞消息時,打開了消息的持久化,那麽即使是內存節點,數據還是安全的放在磁盤。那麽內存節點的性能只能體現在資源管理上,比如增加或刪除隊列(queue),虛擬主機(vrtual hosts),交換機(exchange)等,發送和接受message速度同磁盤節點一樣。一個集群至少要有一個磁盤節點。一個rabbitmq集群中可以共享user,vhost,exchange等,所有的數據和狀態都是必須在所有節點上復制的,對於queue根據集群模式不同,應該有不同的表現。在集群模式下只要有任何一個節點能夠工作,RabbitMQ集群對外就能提供服務。
默認的集群模式,queue創建之後,如果沒有其它policy,則queue就會按照普通模式集群。對於Queue來說,消息實體只存在於其中一個節點,A、B兩個節點僅有相同的元數據,即隊列結構,但隊列的元數據僅保存有一份,即創建該隊列的rabbitmq節點(A節點),當A節點宕機,你可以去其B節點查看,./rabbitmqctl list_queues發現該隊列已經丟失,但聲明的exchange還存在。
當消息進入A節點的Queue中後,consumer從B節點拉取時,RabbitMQ會臨時在A、B間進行消息傳輸,把A中的消息實體取出並經過B發送給consumer,所以consumer應平均連接每一個節點,從中取消息。該模式存在一個問題就是當A節點故障後,B節點無法取到A節點中還未消費的消息實體。如果做了隊列持久化或消息持久化,那麽得等A節點恢復,然後才可被消費,並且在A節點恢復之前其它節點不能再創建A節點已經創建過的持久隊列;如果沒有持久化的話,消息就會失丟。這種模式更適合非持久化隊列,只有該隊列是非持久的,客戶端才能重新連接到集群裏的其他節點,並重新創建隊列。假如該隊列是持久化的,那麽唯一辦法是將故障節點恢復起來。
為什麽RabbitMQ不將隊列復制到集群裏每個節點呢?這與它的集群的設計本意相沖突,集群的設計目的就是增加更多節點時,能線性的增加性能(CPU、內存)和容量(內存、磁盤)。當然RabbitMQ新版本集群也支持隊列復制(有個選項可以配置)。比如在有五個節點的集群裏,可以指定某個隊列的內容在2個節點上進行存儲,從而在性能與高可用性之間取得一個平衡(應該就是指鏡像模式)。
2、鏡像模式:把需要的隊列做成鏡像隊列,存在於多個節點,屬於RabbitMQ的HA方案
該模式解決了上述問題,其實質和普通模式不同之處在於,消息實體會主動在鏡像節點間同步,而不是在consumer取數據時臨時拉取。該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,集群內部的網絡帶寬將會被這種同步通訊大大消耗掉。所以在對可靠性要求較高的場合中適用,一個隊列想做成鏡像隊列,需要先設置policy,然後客戶端創建隊列的時候,rabbitmq集群根據“隊列名稱”自動設置是普通集群模式或鏡像隊列。具體如下:
隊列通過策略來使能鏡像。策略能在任何時刻改變,rabbitmq隊列也近可能的將隊列隨著策略變化而變化;非鏡像隊列和鏡像隊列之間是有區別的,前者缺乏額外的鏡像基礎設施,沒有任何slave,因此會運行得更快。
為了使隊列稱為鏡像隊列,你將會創建一個策略來匹配隊列,設置策略有兩個鍵“ha-mode和 ha-params(可選)”。ha-params根據ha-mode設置不同的值,下面表格說明這些key的選項,如下圖:
以上概念參考地址:http://www.ywnds.com/?p=4741
三、普通集群模式安裝配置
官方文檔https://www.rabbitmq.com/clustering.html
1、環境 CentOS 6.7 IP 172.16.100.94 x86_64 2、軟件包版本: erlang-20.0.4-1.el6.x86_64.rpm rabbitmq-server-3.6.12-1.el6.noarch.rpm 3、安裝 #rpm -ivh erlang-20.0.4-1.el6.x86_64.rpm #yum install socat -y # rabbitmq-server依賴次軟件包 #rpm -ivh rabbitmq-server-3.6.12-1.el6.noarch.rpm 4、啟動3個進程(模擬3臺不同的node) #RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit1 /etc/init.d/rabbitmq-server start #RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit2 /etc/init.d/rabbitmq-server start #RABBITMQ_NODE_PORT=5674 RABBITMQ_NODENAME=rabbit3 /etc/init.d/rabbitmq-server start 查看啟動情況 #netstat -tunlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:25672 0.0.0.0:* LISTEN 25527/beam.smp tcp 0 0 0.0.0.0:25673 0.0.0.0:* LISTEN 26425/beam.smp tcp 0 0 0.0.0.0:25674 0.0.0.0:* LISTEN 27310/beam.smp tcp 0 0 0.0.0.0:4369 0.0.0.0:* LISTEN 25191/epmd tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1778/sshd tcp 0 0 :::5672 :::* LISTEN 25527/beam.smp tcp 0 0 :::5673 :::* LISTEN 26425/beam.smp tcp 0 0 :::5674 :::* LISTEN 27310/beam.smp tcp 0 0 :::4369 :::* LISTEN 25191/epmd tcp 0 0 :::22 :::* LISTEN 1778/sshd 5、結束進程命令 #rabbitmqctl -n rabbit1 stop #rabbitmqctl -n rabbit2 stop #rabbitmqctl -n rabbit3 stop 6、查看狀態: #rabbitmqctl -n rabbit1 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected]]}]}, {running_nodes,[[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}]}] #rabbitmqctl -n rabbit2 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected]]}]}, {running_nodes,[[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}]}] #rabbitmqctl -n rabbit3 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected]]}]}, {running_nodes,[[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}]}] 7、開始配置 停掉rabbit2節點的應用 #rabbitmqctl -n rabbit2 stop_app Stopping rabbit application on node [email protected] 將rabbit2節點加入到[email protected] #rabbitmqctl -n rabbit2 join_cluster [email protected] Clustering node [email protected] with [email protected] 啟動rabbit2應用節點 #rabbitmqctl -n rabbit2 start_app Starting node [email protected] 查看集群狀態 #rabbitmqctl -n rabbit1 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]},{[email protected],[]}]}] #rabbitmqctl -n rabbit2 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]},{[email protected],[]}]}] 可以看到不管是以哪一個節點的身份去查,集群中都有節點rabbit1和rabbit2 #############################################3 現在加入rabbit3 首先停掉rebbit3節點的應用 # rabbitmqctl -n rabbit3 stop_app Stopping rabbit application on node [email protected] # rabbitmqctl -n rabbit3 join_cluster [email protected] Clustering node [email protected] with [email protected] 啟動 # rabbitmqctl -n rabbit3 start_app Starting node [email protected] 查看集群狀態 #rabbitmqctl -n rabbit1 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}, {[email protected],[]}, {[email protected],[]}]}] 註:已經加入群集的節點可以隨時停止,並且宕機對集群來說也是沒事的,在這兩種情況下,集群的其 余部分繼續運行不受影響,並且節點在重新啟動時會自動“趕上”其他集群節點。
四、對集群進行測試:
我們假設關閉rabbit1和rabbit3,在每一個步驟檢查集群狀態 1、關閉rabbit1節點 #rabbitmqctl -n rabbit1 stop Stopping and halting node [email protected] 2、查看集群狀態 # rabbitmqctl -n rabbit2 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]},{[email protected],[]}]}] 可以看到rabbit1節點已經不再running_noeds中了,但是依然在disc列表! #rabbitmqctl -n rabbit3 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]},{[email protected],[]}]}] ############################################################ # rabbitmqctl -n rabbit3 stop #關閉rabbit3 節點 Stopping and halting node [email protected] 3、查看集群狀態 # rabbitmqctl -n rabbit2 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected],[email protected]]}]}, {running_nodes,[[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}]}] 4、現在開啟關閉的節點rabbit1 和rabbit3 #RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit1 /etc/init.d/rabbitmq-server start #RABBITMQ_NODE_PORT=5674 RABBITMQ_NODENAME=rabbit3 /etc/init.d/rabbitmq-server start 5、再查看集群狀態 #rabbitmqctl -n rabbit1 cluster_status Cluster status of node [email protected] [{nodes,[{disc,[[email protected],[email protected],[email protected]]}]}, {running_nodes,[[email protected],[email protected],[email protected]]}, {cluster_name,<<"[email protected]">>}, {partitions,[]}, {alarms,[{[email protected],[]}, {[email protected],[]}, {[email protected],[]}]}] 可以看到3個節點都已經是running狀態了。 一些註意事項: 當整個群集被關閉時,最後一個節點必須是要聯機的第一個節點。如果沒有發生這種情況,節點將等待 30秒鐘,最後一個disc節點重新聯機,之後會失敗。如果最後一個要脫機的節點無法恢復,則可以使用 forget_cluster_node命令將其從集群中刪除。如果所有群集節點都以同時和不受控制的方式停止 (例如斷電),你可以留下一種情況,所有的節點都認為一些其他節點在它們之後停止,在這種情況下 您可以在一個節點上使用force_boot命令,使其再次可引導。 6、為rabbit1節點添加用戶名 #rabbitmqctl -n rabbit1 add_user admin admin123 #rabbitmqctl -n rabbit1 set_user_tags admin administrator #rabbitmqctl -n rabbit1 set_permissions -p / admin ".*" ".*" ".*" 7、開啟web管理界面 #rabbitmq-plugins -n rabbit1 enable rabbitmq_management #會開啟15672端口 在瀏覽器訪問 輸入第6步設置的用戶名和密碼,界面如下:
註:rabbit2和rabbit3之所以是黃色狀態,紅色小箭頭也解釋了。因為我們是在一臺服務器模擬的3個節點,rabbitmq_management界面啟動之後,端口是15672,只啟動了一個,再啟動rabbit2的時候,提示端口被占用,目前不知道如何為管理界面指定不同的端口,後面會繼續研究……
本文出自 “知識體系” 博客,請務必保留此出處http://linuxg.blog.51cto.com/4410110/1965369
Rabbitmq 相關介紹之單機集群配置