RabbitMQ分布式集群架構
RabbitMQ分布式集群架構和高可用性(HA)
https://blog.csdn.net/woogeyu/article/details/51119101
(一) 功能和原理
設計集群的目的
-
允許消費者和生產者在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連接的節點。 |
實例列舉:
queue_args("x-ha-policy":"all") //定義字典來設置額外的隊列聲明參數channel.queue_declare(queue="hello-queue",argument=queue_args)12
如果需要設定特定的節點(以rabbit@localhost為例),再添加一個參數
queue_args("x-ha-policy":"nodes", "x-ha-policy-params":["rabbit@localhost"])channel.queue_declare(queue="hello-queue",argument=queue_args)123
可以通過命令行查看那個主節點進行了同步
rabbitmqctl list_queue name slave_pids synchronised_slave_pids1
(二) 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=5672NODENAME=rabbitNODE_PORT=5673NODENAME=rabbit_011234
-
將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地址 | 工作模式 | 操作系統 |
---|---|---|---|
rabbitmqCluster | 186.16.195.24 | DISK | CentOS 7.0 - 64位 |
rabbitmqCluster01 | 186.16.195.25 | DISK | CentOS 7.0 - 64位 |
rabbitmqCluster02 | 186.16.195.26 | DISK | CentOS 7.0 - 64位 |
cluster部署過程:
-
局域網配置
分別在三個節點的/etc/hosts下設置相同的配置信息
186.16.195.24 rabbitmqCluster
186.16.195.25 rabbitmqCluster01
186.16.195.26 rabbitmqCluster02123
-
設置不同節點間同一認證的Erlang Cookie
采用從主節點copy的方式保持Cookie的一致性
[root@rabbitmqCluster01]# scp /var/lib/rabbitmq/.erlang.cookie 186.16.195.25:/var/lib/rabbitmq
[root@rabbitmqCluster02]# scp /var/lib/rabbitmq/.erlang.cookie 186.16.195.26:/var/lib/rabbitmq12
-
使用 -detached運行各節點
rabbitmqctl stoprabbitmq-server -detached 12
-
查看各節點的狀態
[root@rabbitmqCluster]#rabbitmqctl cluster_status[root@rabbitmqCluster01]#rabbitmqctl cluster_status[root@rabbitmqCluster02]#rabbitmqctl cluster_status123
-
創建並部署集群,以rabbitmqCluster01節點為例:
[root@rabbitmqCluster01]#rabbitmqctl stop_app[root@rabbitmqCluster01]#rabbitmqctl join_cluster rabbit@rabbitmqCluster[root@rabbitmqCluster01]#rabbitmqctl start_app123
-
查看集群狀態
[root@rabbitmqCluster]#rabbitmqctl cluster_status1
RabbitMQ負載均衡配置
前言:從目前來看,基於RabbitMQ的分布式通信框架主要包括兩部分內容,一是要確保可用性和性能,另一個就是編寫當節點發生故障時知道如何重連到集群的應用程序。負載均衡就是解決處理節點的選擇問題。
安裝HAProxy
選擇開源的HAProxy為RabbitMQ集群做負載均衡器,在CentOS 7.0中安裝HAProxy。
-
安裝epel
rpm -ivh http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-5.noarch.rpm//1
-
安裝HAProxy
yum -y install haproxy1
-
配置HAProxy
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bakvim /etc/haproxy/haproxy.cfg12
-
添加配置信息
listen rabbitmq_local_cluster 127.0.0.1:5670 //前段IP,供product和consumer來進行選擇,由於5672端口已經默認使用,這裏選擇5670端口
mode tcp //負載均衡選項
balance roundrobin //輪詢算法將負載發給後臺服務器
server rabbit 127.0.0.1:5672 check inter 5000 rise 2 fall 3//負載均衡中的集群節點配置,這裏選擇的rabbit節點
listen private_monitoring :8100
mode http
option httplog
stats enable
stats uri /stats
stats refresh 60s1234567891011
-
訪問http://localhost:8100/stats就可以看到具體的控制界面。
參考文獻:
-
http://rabbitmq-into-chinese.readthedocs.org/zh_CN/latest/
-
《RabbitMQ實戰-高效部署分布式消息隊列》[美] Alvar Videla,Jason J.W. Williams 著 汪佳南 譯
-
https://geewu.gitbooks.io/rabbitmq-quick/content/
-
RabbitMQ分布式集群架構