RabbitMQ 集羣配置 -docker 版-

一、介紹

在前幾篇文章中,我們詳細的介紹了 RabbitMQ 的內部結構和使用,以及 SpringBoot 和 RabbitMQ 整合,都是基於單臺 RabbitMQ 進行使用的。

我們知道在微服務流行的當下,一旦單臺服務器掛了,基本上就無法提供高可用的服務了,因此爲了保證服務高可用,在生產環境上我們通常的做法是搭建一個 RabbitMQ 集羣,即使某臺 RabbitMQ 故障了,其他正常的 RabbitMQ 服務器依然可以使用,應用程序的持續運行不會受到影響。

二、集羣架構原理

在前幾篇文章中,我們有介紹到 RabbitMQ 內部有各種基礎構件,包括隊列、交換器、綁定、虛擬主機等,他們組成了 AMQP 協議消息通信的基礎,而這些構件以元數據的形式存在,它始終記錄在 RabbitMQ 內部,它們分別是:

這些元數據,其實本質是一張查詢表,裏面包括了交換器名稱和一個隊列的綁定列表,當你將消息發佈到交換器中,實際上是將你所在的信道將消息上的路由鍵與交換器的綁定列表進行匹配,然後將消息路由出去。

消息路由表
有了這個機制,那麼在所有節點上傳遞交換器消息將簡單很多,而 RabbitMQ 所做的事情就是把交換器元數據拷貝到所有節點上,因此每個節點上的每條信道都可以訪問完整的交換器。

如果消息生產者所連接的是節點 2 或者節點 3,此時隊列 1 的完整數據不在該兩個節點上,那麼在發送消息過程中這兩個節點主要起了一個路由轉發作用,根據這兩個節點上的元數據轉發至節點 1 上,最終發送的消息還是會存儲至節點 1 的隊列 1 上。

同樣,如果消息消費者所連接的節點 2 或者節點 3,那這兩個節點也會作爲路由節點起到轉發作用,將會從節點 1 的隊列 1 中拉取消息進行消費。

與常見的集羣主從架構模式不同的地方在於:RabbitMQ 集羣模式下,僅僅只是同步元數據,每個隊列內容還是在自己的服務器節點上

這麼設計主要還是基於集羣本身的性能和存儲空間上來考慮:

既然每個隊列內容還是在自己的服務器節點上,同樣也會帶來新的問題,那就是如果隊列所在服務器掛了,那存在服務器上的隊列數據是不是全部都丟失了?

在單個節點上,RabbitMQ 存儲數據有兩種方案:

在集羣中的每個節點,要麼是內存節點,要麼是磁盤節點,如果是內存節點,會將所有的元數據信息僅存儲到內存中,而磁盤節點則不僅會將所有元數據存儲到內存上, 還會將其持久化到磁盤

在單節點 RabbitMQ 上,僅允許該節點是磁盤節點,這樣確保了節點發生故障或重啓節點之後,所有關於系統的配置與元數據信息都會從磁盤上恢復。

而在 RabbitMQ 集羣上,至少有一個磁盤節點,也就是在集羣環境中需要添加 2 臺及以上的磁盤節點,這樣其中一臺發生故障了,集羣仍然可以保持運行。其它節點均設置爲內存節點,這樣會讓隊列和交換器聲明之類的操作會更加快速,元數據同步也會更加高效。

三、集羣部署

3.1 docker 安裝

可以選 3 臺虛擬機部署 docker,也可以一臺虛擬機上部署 3 個 docker,原理都差不多,目的是布 3 套 rabbitmq 的環境,並能夠互通
我們這爲了方便演示,在同一臺主機上部署 3 臺虛擬機,保證他們互相之間可以連通,我們先創建一個 docker 網絡

docker network create backend

創建完之後可以查看

docker network ls
docker run -d --hostname rabbit_host1 --name rabbitmq1 -p 15672:15672 -p 5672:5672 --network=backend -e RABBITMQ_ERLANG_COOKIE='rabbitmq_cookie' rabbitmq:management
docker run -d --hostname rabbit_host2 --name rabbitmq2 -p 5673:5672 --network=backend -e RABBITMQ_ERLANG_COOKIE='rabbitmq_cookie' rabbitmq:management
docker run -d --hostname rabbit_host3 --name rabbitmq3 -p 5674:5672 --network=backend -e RABBITMQ_ERLANG_COOKIE='rabbitmq_cookie' rabbitmq:management

Erlang Cookie 值必須相同,也就是一個集羣內 RABBITMQ_ERLANG_COOKIE 參數的值必須相同。因爲 RabbitMQ 是用 Erlang 實現的,Erlang Cookie 相當於不同節點之間通訊的密鑰,Erlang 節點通過交換 Erlang Cookie 獲得認證。

3.2 將節點加入到集羣裏

第 1 臺不動,另外兩臺分別執行下面命令

第 2 臺

docker exec -it rabbitmq2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq_host1
rabbitmqctl start_app
exit

第 3 臺

docker exec -it rabbitmq3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbitmq_host1
rabbitmqctl start_app
exit

主要參數:

--ram 表示設置爲內存節點,忽略次參數默認爲磁盤節點。該配置啓動了 3 個節點,1 個磁盤節點和 2 個內存節點。

設置好之後,使用 http://ip:15672 進行訪問,默認賬號密碼:guest/guest

可以看到,已經有多個節點了。

四 鏡像隊列

部署好集羣以後,就是設置如何實時的同步隊列和其中的數據,這邊就會使用 RabbitMQ 的鏡像功能

4.1 策略 policy 概念

使用 RabbitMQ 鏡像功能,需要基於 RabbitMQ 策略來實現,策略 policy 是用來控制和修改羣集範圍的某個 vhost 隊列行爲和 Exchange 行爲。策略 policy 就是要設置哪些 Exchange 或者 queue 的數據需要複製、同步,以及如何複製同步。

爲了使隊列成爲鏡像隊列,需要創建一個策略來匹配隊列,設置策略有兩個鍵 “ha-mode 和 ha-params(可選)”。ha-params 根據 ha-mode 設置不同的值,下表說明這些 key 的選項。

4.2 添加策略

登錄 rabbitmq 管理頁面 ——> Admin ——> Policies ——> Add / update a policy

name:隨便取,策略名稱
Pattern:^ 匹配符,只有一個 ^ 代表匹配所有
Definition:ha-mode=all 爲匹配類型,分爲 3 種模式:all(表示所有的 queue)
或者使用命令:

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

4.3 查看效果

此策略會同步所在同一 VHost 中的交換器和隊列數據。設置好 policy 之後,使用 http://ip:15672 再次進行訪問,可以看到隊列鏡像同步。

加餐 - spring boot 中配置 rabbitmq 集羣

單機

spring:
  rabbitmq:
    host: localhost
    port: 5672
    username: username
    password: password

或者使用 address

spring:
  rabbitmq:
    addresses:ip1:port1
    username: username
    password: password

集羣

addresses 節點用逗號分隔

spring:
  rabbitmq:
    addresses:ip1:port1,ip2:port2,ip3:port3
    username: username
    password: password

至些 rabbitmq 系列寫完了,大家可以實操一下,有了消息隊列,高併發再也不怕了。

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/1ehM5NsyAhpknwTAoDXuLw