(一) 功能和原理
設計集群的目的
-
允許消費者和生產者在RabbitMQ節點崩潰的情況下繼續運行
-
通過增加更多的節點來擴展消息通信的吞吐量
1 集群配置方式
RabbitMQ可以通過三種方法來部署分布式集群系統,分別是:cluster,federation,shovel
-
cluster:
-
不支持跨網段,用於同一個網段內的局域網
-
可以隨意的動態增加或者減少
-
節點之間需要運行相同版本的RabbitMQ和Erlang
-
federation:應用於廣域網,允許單台服務器上的交換機或隊列接收發布到另一台服務器上交換機或隊列的消息,可以是單獨機器或集群。federation隊列類似於單向點對點連接,消息會在聯盟隊列之間轉發任意次,直到被消費者接受。通常使用federation來連接internet上的中間服務器,用作訂閱分發消息或工作隊列。
-
shovel:連接方式與federation的連接方式類似,但它工作在更低層次。可以應用於廣域網。
2 節點類型
-
RAM node:內存節點將所有的隊列、交換機、綁定、用戶、權限和vhost的元數據定義存儲在內存中,好處是可以使得像交換機和隊列聲明等操作更加的快速。
-
Disk node:將元數據存儲在磁盤中,單節點系統只允許磁盤類型的節點,防止重啟RabbitMQ的時候,丟失系統的配置信息。
問題說明: RabbitMQ要求在集群中至少有一個磁盤節點,所有其他節點可以是內存節點,當節點加入或者離開集群時,必須要將該變更通知到至少一個磁盤節點。如果集群中唯一的一個磁盤節點崩潰的話,集群仍然可以保持運行,但是無法進行其他操作(增刪改查),直到節點恢復。
解決方案:設置兩個磁盤節點,至少有一個是可用的,可以保存元數據的更改。
3 Erlang Cookie
Erlang Cookie是保證不同節點可以相互通信的密鑰,要保證集群中的不同節點相互通信必須共享相同的Erlang Cookie。具體的目錄存放在/var/lib/rabbitmq/.erlang.cookie。
說明: 這就要從rabbitmqctl命令的工作原理說起,RabbitMQ底層是通過Erlang架構來實現的,所以rabbitmqctl會啟動Erlang節點,並基於Erlang節點來使用Erlang系統連接RabbitMQ節點,在連接過程中需要正確的Erlang Cookie和節點名稱,Erlang節點通過交換Erlang Cookie以獲得認證。
4 鏡像隊列
功能和原理
RabbitMQ的Cluster集群模式一般分為兩種,普通模式和鏡像模式。
-
普通模式:默認的集群模式,以兩個節點(rabbit01、rabbit02)為例來進行說明。對於Queue來說,消息實體只存在於其中一個節點rabbit01(或者rabbit02),rabbit01和rabbit02兩個節點僅有相同的元數據,即隊列的結構。當消息進入rabbit01節點的Queue后,consumer從rabbit02節點消費時,RabbitMQ會臨時在rabbit01、rabbit02間進行消息傳輸,把A中的消息實體取出並經過B發送給consumer。所以consumer應盡量連接每一個節點,從中取消息。即對於同一個邏輯隊列,要在多個節點建立物理Queue。否則無論consumer連rabbit01或rabbit02,出口總在rabbit01,會產生瓶頸。當rabbit01節點故障后,rabbit02節點無法取到rabbit01節點中還未消費的消息實體。如果做了消息持久化,那么得等rabbit01節點恢復,然后才可被消費;如果沒有持久化的話,就會產生消息丟失的現象。
-
鏡像模式:將需要消費的隊列變為鏡像隊列,存在於多個節點,這樣就可以實現RabbitMQ的HA高可用性。作用就是消息實體會主動在鏡像節點之間實現同步,而不是像普通模式那樣,在consumer消費數據時臨時讀取。缺點就是,集群內部的同步通訊會占用大量的網絡帶寬。
實現機制
鏡像隊列實現了RabbitMQ的高可用性(HA),具體的實現策略如下所示:
ha-mode | ha-params | 功能 |
---|---|---|
all | 空 | 鏡像隊列將會在整個集群中復制。當一個新的節點加入后,也會在這 個節點上復制一份。 |
exactly | count | 鏡像隊列將會在集群上復制count份。如果集群數量少於count時候,隊列會復制到所有節點上。如果大於Count集群,有一個節點crash后,新進入節點也不會做新的鏡像。 |
nodes | node name | 鏡像隊列會在node name中復制。如果這個名稱不是集群中的一個,這不會觸發錯誤。如果在這個node list中沒有一個節點在線,那么這個queue會被聲明在client連接的節點。 |
語法講解:
# rabbitmqctl set_policy [-p coresystem] ha-all "^" '{"ha-mode":"all"}'
"coresystem" vhost名稱, "^"匹配所有的隊列, ha-all 策略名稱為ha-all, '{"ha-mode":"all"}' 策略模式為 all 即復制到所有節點,包含新增節點。
則此時鏡像隊列設置成功。(這里的虛擬主機coresystem是代碼中需要用到的虛擬主機,虛擬主機的作用是做一個消息的隔離,本質上可認為是一個rabbitmq-server,是否增加虛擬主機,增加幾個,這是由開發中的業務決定,即有哪幾類服務,哪些服務用哪一個虛擬主機,這是一個規划)。
可以用查看使用的群集模式
# rabbitmqctl list_policies
(二) RabbitMQ Cluster 配置
1 單機多節點部署
在啟動RabbitMQ節點之后,服務器默認的節點名稱是Rabbit和監聽端口5672,如果想在同一台機器上啟動多個節點,那么其他的節點就會因為節點名稱和端口與默認的沖突而導致啟動失敗,可以通過設置環境變量來實現,具體方法如下:
-
首先在機器上設置兩個節點rabbit和rabbit_01
rabbitmqctl stop //先停止運行節點,再進行集群部署
RABBITMQ_NODE_PORT=5672 RABBITMQ_NODENAME=rabbit //設置環境變量指定端口和節點名稱
rabbitmq-server -detached //后台啟動節點
RABBITMQ_NODE_PORT=5673 RABBITMQ_NODENAME=rabbit_01 //設置環境變量指定端口和節點名稱
rabbitmq-server -detached //后台啟動節點12345
或者通過添加/etc/rabbitmq/rabbitmq-env.conf文件來進行設置:
NODE_PORT=5672
NODENAME=rabbit
NODE_PORT=5673
NODENAME=rabbit_01
-
將rabbit_01節點添加到第一個集群節點rabbit中
rabbitmqctl -n rabbit_01@localhost stop_app //停止rabbit_01節點的應用
rabbitmqctl -n rabbit_01@localhost join_cluster rabbit@localhost //將rabbit_01添加到集群節點rabbit中去
rabbitmqctl cluster_status //查看集群節點的狀態
rabbitmqctl -n rabbit_01@localhost start_app //啟動rabbit_01節點的應用1234
可以看到如下信息,說明節點添加成功,表明都是磁盤類型的節點
Cluster status of node rabbit@localhost ...[{nodes,[{disc,[rabbit@localhost,rabbit_01@localhost]}]}, {running_nodes,[rabbit@localhost]}, {cluster_name,<<"rabbit@localhost">>}, {partitions,[]}, {alarms,[{rabbit@localhost,[]}]}]1234567
2 多機多節點部署
不同於單機多節點的情況,在多機環境,如果要在cluster集群內部署多個節點,需要注意兩個方面:
-
保證需要部署的這幾個節點在同一個局域網內
-
需要有相同的Erlang Cookie,否則不能進行通信,為保證cookie的完全一致,采用從一個節點copy的方式
環境介紹:
RabbitMQ節點 | IP地址 | 工作模式 | 操作系統 |
---|---|---|---|
node1 | 10.10.91.57 |
DISK | CentOS 7.2 - 64位 |
node2 | 10.10.91.62 |
DISK | CentOS 7.2 - 64位 |
node3 | 10.10.91.63 |
DISK | CentOS 7.2 - 64位 |
cluster部署過程:
-
局域網配置
分別在三個節點的/etc/hosts下設置相同的配置信息
10.10.91.57 node1 10.10.91.62 node2 10.10.91.63 node3
-
設置不同節點間同一認證的Erlang Cookie
采用從主節點copy的方式保持Cookie的一致性
注意:rabbit
[root@node1 ~]# scp /var/lib/rabbitmq/.erlang.cookie 10.10.91.62:/var/lib/rabbitmq [root@node1 ~]# scp /var/lib/rabbitmq/.erlang.cookie 10.10.91.63:/var/lib/rabbitmq
-
使用 -detached運行各節點
# rabbitmq-server -detached
或
# systemctl restart rabbitmq-server.service
-
查看各節點的狀態
#rabbitmqctl cluster_status
-
創建並部署集群,在node2和node3上執行:
# rabbitmqctl stop_app
# rabbitmqctl reset
# rabbitmqctl join_cluster rabbit@node1
# rabbitmqctl start_app
-
查看集群狀態
# rabbitmqctl cluster_status
更改節點類型(內存型或磁盤型)
# rabbitmqctl stop_app # rabbitmqctl change_cluster_node_type disc 或 # rabbitmqctl change_cluster_node_type ram # rabbitmqctl start_app
也可以通過在配置文件直接寫,如下:
[ {rabbit,[{cluster_nodes, {['rabbit@node1', 'rabbit@node2', 'rabbit@node3'], disc|ram}}]} ].
然后直接啟用
(三) RabbitMQ負載均衡配置
前言:從目前來看,基於RabbitMQ的分布式通信框架主要包括兩部分內容,一是要確保可用性和性能,另一個就是編寫當節點發生故障時知道如何重連到集群的應用程序。負載均衡就是解決處理節點的選擇問題。
安裝HAProxy
選擇開源的HAProxy為RabbitMQ集群做負載均衡器,在CentOS 7.0中安裝HAProxy。
-
安裝epel
yum install -y epel-release
-
安裝HAProxy
yum -y install haproxy
-
配置HAProxy
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak vim /etc/haproxy/haproxy.cfg
-
添加配置信息
bind 0.0.0.0:5672
mode tcp
balance roundrobin
option tcplog
option tcpka
server concar-rmq01

server concar-rmq02

server concar-rmq03

-
訪問http://IP:5672就可以看到具體的控制界面。