通常狀況下,若是隻是爲了探究 RabbitMQ 或者驗證業務工程的正確性那麼在本地環境或者測試環境上使用其單實例部署就能夠了,可是出於 MQ 中間件自己的可靠性、併發性、吞吐量和消息堆積能力等問題的考慮,在生產環境上通常都會考慮使用 RabbitMQ 的集羣方案。node
本文檔旨在介紹 RabbitMQ 集羣的工做原理以及在 CentOS 7 系統上安裝配置具有高可用性和具有必定負載能力的 RabbitMQ 集羣。linux
RabbitMQ 這款消息隊列中間件產品自己是基於 Erlang 編寫,Erlang 語言天生具有分佈式特性(經過同步 Erlang 集羣各節點的 magic cookie 來實現)。所以,RabbitMQ 自然支持 Clustering。這使得 RabbitMQ 自己不須要像ActiveMQ、Kafka 那樣經過 ZooKeeper 分別來實現 HA 方案和保存集羣的元數據。集羣是保證可靠性的一種方式,同時能夠經過水平擴展以達到增長消息吞吐量能力的目的。git
RabbitMQ 集羣有兩種模式:github
RabbitMQ 集羣主機環境以下:bash
mq-node1(master) 10.200.100.231 master.yeaheo.com mq-node2(node01) 10.200.100.231 node01.yeaheo.com mq-node3(node02) 10.200.100.231 node02.yeaheo.com
各主機系統環境及 MQ 版本以下:cookie
$ cat /etc/redhat-release CentOS Linux release 7.5.1804 (Core) $ uname -r 3.10.0-862.el7.x86_64 Erlang : 21.1 RabbitMQ: v3.7.9
修改各主機 hosts
文件以下:網絡
.... 10.200.100.231 master master.yeaheo.com 10.200.100.217 node01 node01.yeaheo.com 10.200.100.218 node02 node02.yeaheo.com ....
配置 RabbitMQ 集羣首先須要在各個主機上安裝並配置 Erlang 和 RabbitMQ ,Erlang安裝過程能夠參考: rabbitmq-erlang-installation.md RabbitMQ 具體過程能夠參考:rabbitmq-single-installation.md併發
當 Erlang 和 RabbitMQ 安裝完成後就能夠配置 RabbitMQ 集羣了。app
本次部署集羣時都是將其餘兩個 RabbitMQ 加入到 master 主機現有集羣中。socket
rabbitmq-server 啓動時,會一塊兒啓動節點和應用,它預先設置 RabbitMQ 應用爲 standalone 模式。要將一個節點加入到現有的集羣中,你須要中止這個應用,並將節點設置爲原始狀態。若是使用 rabbitmqctl stop
,應用和節點都將被關閉。因此使用 rabbitmqctl stop_app
僅僅關閉應用
RabbitMQ 利用 erlang 的分佈式特性組建集羣,erlang 集羣經過 magic cookie 實現,此 cookie 保存在$home/.erlang.cookie
,這裏即:/var/lib/rabbitmq/.erlang.cookie
,須要保證集羣各節點的此 cookie 一致,能夠選取一個節點的 cookie,採用 scp 同步到其餘節點:
$ scp /var/lib/rabbitmq/.erlang.cookie root@node01:/var/lib/rabbitmq/.erlang.cookie $ scp /var/lib/rabbitmq/.erlang.cookie root@node02:/var/lib/rabbitmq/.erlang.cookie
更換 cookie 後須要重啓 RabbitMQ 服務:
$ systemctl stop rabbitmq-server.service $ systemctl start rabbitmq-server.service
全部節點須要使用 -detached
參數啓動服務:
# 須要在全部節點上執行 $ rabbitmqctl stop $ rabbitmq-server -detached
由於將其餘兩個 RabbitMQ 加入到 master 主機現有集羣中,因此只須要在 node01
和 node02
上操做便可:
node01 主機(10.200.100.217)上操做:
node01$ rabbitmqctl stop_app node01$ rabbitmqctl join_cluster rabbit@master ####這裏集羣的名字必定不要寫錯了 node01$ rabbitmqctl start_app
集羣名字通常能夠在
master
主機的日誌文件中看到,須要注意的是這個集羣名字須要和日誌文件中保持一致,不然加入集羣時會報錯
node02 主機(10.200.100.218)上操做:
node02$ rabbitmqctl stop_app node02$ rabbitmqctl join_cluster rabbit@master ####這裏集羣的名字必定不要寫錯了 node02$ rabbitmqctl start_app
查看集羣狀態:
$ rabbitmqctl cluster_status Cluster status of node rabbit@master ... [{nodes,[{disc,[rabbit@master,rabbit@node01]},{ram,[rabbit@node02]}]}, {running_nodes,[rabbit@node02,rabbit@node01,rabbit@master]}, {cluster_name,<<"rabbit@master">>}, {partitions,[]}, {alarms,[{rabbit@node02,[]},{rabbit@node01,[]},{rabbit@master,[]}]}]
此時 node01
與 node02
也會自動創建鏈接,集羣配置完成。
若是要使用內存節點,則可使用
rabbitmqctl join_cluster --ram rabbit@master
加入集羣。
RabbitMQ 節點分爲內存節點和磁盤節點:
1)內存節點(RAM):內存節點將全部的隊列、交換機、綁定、用戶、權限和vhost的元數據定義存儲在內存中
2)磁盤節點(Disk):將元數據存儲在磁盤中,單節點系統只容許磁盤類型的節點,防止重啓RabbitMQ的時候,丟失系統的配置信息。
若是須要切換節點類型,能夠參考以下命令:
#若是節點已經是"disk"節點,能夠修改成內存節點 $ rabbitmqctl stop_app $ rabbitmqctl change_cluster_node_type ram $ rabbitmqctl start_app
1)RabbitMQ要求在集羣中至少有一個磁盤節點,全部其餘節點能夠是內存節點,當節點加入或者離開集羣時,必需要將該變動通知到至少一個磁盤節點。若是集羣中惟一的一個磁盤節點崩潰的話,集羣仍然能夠保持運行,可是沒法進行其餘操做(增刪改查),直到節點恢復, 或者能夠設置兩個磁盤節點,以保持有一個是可用的。
2)內存節點雖然不寫入磁盤,可是它執行比磁盤節點要好。
3)若是集羣中只有內存節點,那麼不能中止它們,不然全部的狀態,消息等都會丟失。
通過上述配置,集羣雖然搭建成功,但只是默認的普通集羣,exchange,binding 等數據能夠複製到集羣各節點。
但對於隊列來講,各節點只有相同的元數據,即隊列結構,但隊列實體只存在於建立改隊列的節點,即隊列內容不會複製(從其他節點讀取,能夠創建臨時的通訊傳輸)。這樣此節點宕機後,其他節點沒法從宕機節點獲取還未消費的消息實體。若是作了持久化,則須要等待宕機節點恢復,期間其他節點不能建立宕機節點已建立過的持久化隊列;若是未作持久化,則消息丟失。
下邊來配置策略,策略名稱爲 ha-all,通配符 ^ 表示匹配到的全部隊列,複製到全部節點,在任一節點上執行:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
也能夠複製匹配到的隊列到集羣中的任意兩個或多個節點,而不是到全部節點,並進行自動同步:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
或者複製匹配到的隊列到集羣中的指定節點:
$ rabbitmqctl set_policy ha-all "^" '{"ha-mode":"nodes","ha-params":["rabbit@node01","rabbit@node02"]}'
至此,鏡像隊列策略配置完成,同時也實現了 HA。
咱們在10.200.100.218
主機上直接用 yum 安裝 HAProxy 便可:
$ yum -y install haproxy
修改 HAProxy 配置文件 /etc/haproxy/haproxy.cfg
以下:
global log 127.0.0.1 local2 chroot /var/lib/haproxy pidfile /var/run/haproxy.pid maxconn 4000 user haproxy group haproxy daemon stats socket /var/lib/haproxy/stats defaults mode tcp log global option tcplog option dontlognull retries 3 timeout http-request 10s timeout queue 1m timeout connect 10s timeout client 1m timeout server 1m timeout http-keep-alive 10s timeout check 10s maxconn 3000 listen rabbitmq_cluster 0.0.0.0:5670 mode tcp balance roundrobin server node1 10.200.100.217:5672 check inter 2000 rise 2 fall 3 server node2 10.200.100.218:5672 check inter 2000 rise 2 fall 3 server node3 10.200.100.231:5672 check inter 2000 rise 2 fall 3 listen monitor 0.0.0.0:8100 mode http option httplog stats enable stats uri /stats stats refresh 5s
重啓 HAProxy:
$ systemctl restart haproxy.service
以後就能夠經過 http://10.200.100.218:8100/stats
查看 HAProxy 的狀態了。
若是用的是雲主機,能夠利用雲服務商本身的 LB,不必定要用 HAProxy