高可用RabbitMQ集羣的搭建及原理分析

前言

任何一個服務,如果僅僅是單機部署,那麼性能總是有上限的,RabbitMQ 也不例外,當單臺 RabbitMQ 服務處理消息的能力到達瓶頸時,可以通過集羣來實現高可用和負載均衡。

RabbitMQ 集羣知多少

通常情況下,在集羣中我們把每一個服務稱之爲一個節點,在 RabbitMQ 集羣中,節點類型可以分爲兩種:

  • 內存節點:元數據存放於內存中。爲了重啓後能同步數據,內存節點會將磁盤節點的地址存放於磁盤之中,除此之外,如果消息被持久化了也會存放於磁盤之中,因爲內存節點讀寫速度快,一般客戶端會連接內存節點。

  • 磁盤節點:元數據存放於磁盤中(默認節點類型),需要保證至少一個磁盤節點,否則一旦宕機,無法恢復數據,從而也就無法達到集羣的高可用目的。

PS:元數據,指的是包括隊列名字屬性、交換機的類型名字屬性、綁定信息、vhost等基礎信息,不包括隊列中的消息數據。

RabbitMQ 中的集羣主要有兩種模式:普通集羣模式和鏡像隊列模式。

普通集羣模式

在普通集羣模式下,集羣中各個節點之間只會相互同步元數據,也就是說,消息數據不會被同步。那麼問題就來了,假如我們連接到 A 節點,但是消息又存儲在 B 節點又怎麼辦呢?

不論是生產者還是消費者,假如連接到的節點上沒有存儲隊列數據,那麼內部會將其轉發到存儲隊列數據的節點上進行存儲。雖然說內部可以實現轉發,但是因爲消息僅僅只是存儲在一個節點,那麼假如這節點掛了,消息是不是就沒有了?這個問題確實存在,所以這種普通集羣模式並沒有達到高可用的目的。

鏡像隊列模式

鏡像隊列模式下,節點之間不僅僅會同步元數據,消息內容也會在鏡像節點間同步,可用性更高。這種方案提升了可用性的同時,因爲同步數據之間也會帶來網絡開銷從而在一定程度上會影響到性能。

RabbitMQ 集羣搭建

接下來讓我們一起嘗試搭建一個 RabbitMQ 集羣:

  1. 假如之前啓動過單機版,那麼先刪除舊數據 rm -rf /var/lib/rabbitmq/mnesia 或者刪除安裝目錄內的 var/lib/rabbitmq/mnesia,我本機是安裝在安裝目錄下,所以執行的是命令 rm -rf /usr/local/rabbitmq_server-3.8.4/var/lib/rabbitmq/mnesia/

  2. 接下來需要啓動以下三個命令來啓動三個不同端口號的 RabbitMQ 服務,除了指定 RabbitMQ 服務端口之後還需要額外指定後臺管理系統的端口,而且必須指定 node 名的前綴,因爲集羣中是以節點名來進行通信的,所以節點名必須唯一,默認的節點名是 rabbit@hostname,下面的命令表示指定了前綴:

RABBITMQ_NODE_PORT=5672 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15672}]" RABBITMQ_NODENAME=rabbit1 rabbitmq-server -detached
RABBITMQ_NODE_PORT=5673 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15673}]" RABBITMQ_NODENAME=rabbit2 rabbitmq-server -detached
RABBITMQ_NODE_PORT=5674 RABBITMQ_SERVER_START_ARGS="-rabbitmq_management listener [{port,15674}]" RABBITMQ_NODENAME=rabbit3 rabbitmq-server -detached

啓動之後進入
/usr/local/rabbitmq_server-3.8.4/var/lib/rabbitmq/mnesia/
 目錄查看,發現創建了 3 個節點信息:


另外通過 ps -ef | grep rabbit 也可以發現三個服務進程被啓動。

  1. 現在啓動的三個服務彼此之間還沒有聯繫,現在我們需要以其中一個節點爲主節點,然後其餘兩個節點需要加入主節點,形成一個集羣服務,需要注意的是加入集羣之前,需要重置節點信息,即不允許帶有數據的節點加入集羣。

//rabbit2 節點重置後加入集羣
rabbitmqctl -n rabbit2 stop_app
rabbitmqctl -n rabbit2 reset
rabbitmqctl -n rabbit2 join_cluster --ram rabbit1@`hostname -s` //--ram 表示這是一個內存節點
rabbitmqctl -n rabbit2 start_app

rabbitmqctl -n rabbit3 stop_app
rabbitmqctl -n rabbit3 reset
rabbitmqctl -n rabbit3 join_cluster --disc rabbit1@`hostname -s` //--disc表示磁盤節點(默認也是磁盤節點)
rabbitmqctl -n rabbit3 start_app
  1. 成功之後,執行命令 rabbitmqctl cluster_status 查詢節點 rabbit1 的狀態,可以看到下圖所示,兩個磁盤節點一個內存節點:


  1. 需要注意的是,到這裏啓動的集羣只是默認的普通集羣,如果想要配置成鏡像集羣,則需要執行以下命令:

rabbitmqctl -n rabbit1 set_policy ha-all "^" '{"ha-mode":"all"}'

到這裏 RabbitMQ 集羣就算搭建完成了,不過需要注意的是,這裏因爲是單機版本,所以沒有考慮 .erlang.cookie 文件保持一致。

基於 HAProxy + Keepalived 高可用集羣

假如一個 RabbitMQ 集羣中,有多個內存節點,我們應該連接到哪一個節點呢?這個選擇的策略如果放在客戶端做,那麼會有很大的弊端,最嚴重的的就是每次擴展集羣都要修改客戶端代碼,所以這種方式並不是很可取,所以我們在部署集羣的時候就需要一箇中間代理組件,這個組件要能夠實現服務監控和轉發,比如 Redis 中的 Sentinel(哨兵)集羣模式,哨兵就可以監聽 Redis 節點並實現故障轉移。

在 RabbitMQ 集羣中,通過 Keepalived 和 HAProxy 兩個組件實現了集羣的高可用性和負載均衡功能。

HAProxy

HAProxy 是一個開源的、高性能的負載均衡軟件,同樣可以作爲負載均衡軟件的還有 nginxlvs 等。 HAproxy 支持 7 層負載均衡和 4 層負載均衡。

負載均衡

所謂的 7 層負載均衡和 4 層負載均衡針對的是 OSI 模型而言,如下圖所示就是一個 OSI 通信模型:


上圖中看到,第 7 層對應了應用層,第 4 層對應了傳輸層。常用的負載均衡軟件如 nginx 一般工作在第 7 層,lvs(Linux Virtual Server)一般工作在第 4 層。

  • 4 層負載:

4 層負載使用了 NAT (Network Address Translation)技術,即:網絡地址轉換。收到客戶端請求時,可以通過修改數據包裏的源 IP 和端口,然後把數據包轉發到對應的目標服務器。4 層負載均衡只能根據報文中目標地址和源地址對請求進行轉發,無法判斷或者修改請求資源的具體類型。

  • 7 層負載:

根據客戶端請求的資源路徑,轉發到不同的目標服務器。

高可用 HAProxy

HAProxy 雖然實現了負載均衡,但是假如只是部署一個 HAProxy,那麼其本身也存在宕機的風險。一旦 HAProxy 宕機,那麼就會導致整個集羣不可用,所以我們也需要對 HAProxy 也實現集羣,那麼假如 HAProxy 也實現了集羣,客戶端應該連接哪一臺服務呢?問題似乎又回到了起點,陷入了無限循環中...

Keepalived

爲了實現 HAProxy 的高可用,需要再引入一個 Keepalived 組件,Keepalived 組件主要有以下特性:

  • 具有負載功能,可以監控集羣中的節點狀態,如果集羣中某一個節點宕機,可以實現故障轉移。

  • 其本身也可以實現集羣,但是隻能有一個 master 節點。

  • master 節點會對外提供一個虛擬 IP,應用端只需要連接這一個 IP 就行了。可以理解爲集羣中的 HAProxy 節點會同時爭搶這個虛擬 IP,哪個節點爭搶到,就由哪個節點來提供服務。

VRRP 協議

VRRP 協議即虛擬路由冗餘協議(Virtual Router Redundancy Protocol)。Keepalived 中提供的虛擬 IP 機制就屬於 VRRP,它是爲了避免路由器出現單點故障的一種容錯協議。

總結

本文主要介紹了 RaabbitMQ 集羣的相關知識,並對比了普通集羣和鏡像集羣的區別,最後通過實踐搭建了一個 RabbitMQ 集羣,同時也介紹了普通的集羣存在一些不足,可以結合 HAProxy 和 Keepalived 組件來實現真正的高可用分佈式集羣服務。

END

版權申明:內容來源網絡,版權歸原創者所有。除非無法確認,我們都會標明作者及出處,如有侵權煩請告知,我們會立即刪除並表示歉意。謝謝。


如果你覺得文章不錯,文末的贊 👍 又回來啦, 記得給我「點贊」和「在看」哦~



本文分享自微信公衆號 - JAVA高級架構(gaojijiagou)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章