RabbitMQ分布式叢集架構和高可用性
(一) 功能和原理
設計叢集的目的
允許消費者和生産者在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)
如果需要設定特定的節點(以rabbit@localhost為例),再添加一個參數
queue_args("x-ha-policy":"nodes",
"x-ha-policy-params":["rabbit@localhost"])
channel.queue_declare(queue="hello-queue",argument=queue_args)
可以通過指令行檢視那個主節點進行了同步
rabbitmqctl list_queue name slave_pids synchronised_slave_pids
(二) 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 //背景啟動節點
或者通過添加/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節點的應用
//可以看到如下資訊,說明節點添加成功,表明都是磁盤類型的節點
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,[]}]}]
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 rabbitmqCluster02
設定不同節點間同一認證的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/rabbitmq
使用 -detached運作各節點
rabbitmqctl stop
rabbitmq-server -detached
檢視各節點的狀态
[root@rabbitmqCluster]#rabbitmqctl cluster_status
[root@rabbitmqCluster01]#rabbitmqctl cluster_status
[root@rabbitmqCluster02]#rabbitmqctl cluster_status
建立并部署叢集,以rabbitmqCluster01節點為例:
[root@rabbitmqCluster01]#rabbitmqctl stop_app
[root@rabbitmqCluster01]#rabbitmqctl join_cluster rabbit@rabbitmqCluster
[root@rabbitmqCluster01]#rabbitmqctl start_app
檢視叢集狀态
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//
安裝HAProxy
yum -y install haproxy
配置HAProxy
cp /etc/haproxy/haproxy.cfg /etc/haproxy/haproxy.cfg.bak
vim /etc/haproxy/haproxy.cfg
添加配置資訊
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 60s
通路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/
轉自:https://blog.csdn.net/woogeyu/article/details/51119101