本文介紹 RabbitMQ 叢集的 Docker 化部署,最開始是想通過 DockerSwarm 方式來部署的,但是 RabbitMQ 節點加入叢集時一直失敗,在網上找了很多辦法,始終沒有解決這個問題,無奈隻能放棄。是以最終采用配置 hosts 檔案方式來保證節點之間的通信,下面來進行詳細說明。
部署環境
- 系統:CentOS8
- 兩台伺服器:10.1.1.1/10.1.1.2
docker-compose 檔案
version: '3'
services:
rabbit1:
container_name: rabbit1
image: rabbitmq:3.7-management-alpine
restart: always
hostname: rabbit1
extra_hosts:
- "rabbit1:10.1.1.1"
- "rabbit2:10.1.1.2"
environment:
- RABBITMQ_ERLANG_COOKIE=MY_COOKIE
- RABBITMQ_DEFAULT_USER=MY_USER
- RABBITMQ_DEFAULT_PASS=MY_PASS
ports:
- "4369:4369"
- "5671:5671"
- "5672:5672"
- "15671:15671"
- "15672:15672"
- "25672:25672"
複制
這樣,10.1.1.1 上的 docker-compose 檔案就寫好了,部署另一台時,隻要将
rabbit1
改成
rabbit2
就可以了。如果是更多台伺服器的話,也是同樣的道理,将 IP 配置到
extra_hosts
參數下即可。
啟動服務
在兩台伺服器上分别執行:
# docker-compose up -d
複制
加入叢集
如果将
rabbit1
作為主節點的話,需要在
rabbit2
上執行指令,将其加入到叢集,如下:
# docker exec -it rabbit2 /bin/bash
rabbit2# rabbitmqctl stop_app
rabbit2# rabbitmqctl reset
rabbit2# rabbitmqctl join_cluster rabbit@rabbit1
rabbit2# rabbitmqctl start_app
複制
預設情況下,RabbitMQ 啟動後是磁盤節點,如果想以記憶體節點方式加入,可以加
--ram
參數。
如果想要修改節點類型,可以使用指令:
# rabbitmqctl change_cluster_node_type disc(ram)
複制
修改節點類型之前需要先
rabbitmqctl stop_app
。
通過下面指令來檢視叢集狀态:
# rabbitmqctl cluster_status
複制
注意,由于 RAM 節點僅将内部資料庫表存儲在記憶體中,是以在記憶體節點啟動時必須從其他節點同步這些資料,是以一個叢集必須至少包含一個磁盤節點。
HAProxy 負載均衡
ha 同樣采用 Docker 方式來部署,先看一下 haproxy.cfg 配置檔案:
# Simple configuration for an HTTP proxy listening on port 80 on all
# interfaces and forwarding requests to a single backend "servers" with a
# single server "server1" listening on 127.0.0.1:8000
global
daemon
maxconn 256
defaults
mode http
timeout connect 5000ms
timeout client 5000ms
timeout server 5000ms
listen rabbitmq_cluster
bind 0.0.0.0:5677
option tcplog
mode tcp
balance leastconn
server rabbit1 10.1.1.1:5672 weight 1 check inter 2s rise 2 fall 3
server rabbit2 10.2.2.2:5672 weight 1 check inter 2s rise 2 fall 3
listen http_front
bind 0.0.0.0:8002
stats uri /haproxy?stats
listen rabbitmq_admin
bind 0.0.0.0:8001
server rabbit1 10.1.1.1:15672
server rabbit2 10.1.1.2:15672
複制
再看一下 docker-compose 檔案:
version: '3'
services:
haproxy:
container_name: rabbit-haproxy
image: haproxy
restart: always
hostname: haproxy
network_mode: rabbitmq_default
volumes:
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
ports:
- "5677:5677"
- "8001:8001"
- "8002:8002"
複制
啟動之後,就可以通過 ha 的位址來通路 RabbitMQ 叢集管理頁面了。
如果公司内部有現成的負載均衡,比如 LVS,那麼也可以省略這一步。
其實到這裡,叢集就可以正常使用了,但還有很重要的一點需要做些說明。
叢集模式
普通模式
- 對于 Queue 來說,消息實體隻存在于其中一個節點,A、B 兩個節點僅有相同的中繼資料,即隊列結構。
- 當消息進入 A 節點的隊列中後,消費者從 B 節點拉取時,RabbitMQ 會臨時在 A、B 間進行消息傳輸,把 A 中的消息實體取出并經過 B 發送給消費者。
- 是以,消費者應盡量連接配接每一個節點,從中取消息。即對于同一個邏輯隊列,要在多個節點建立實體隊列,否則,無論消費者連 A 或者連 B,出口總在 A,會産生瓶頸。
- 該模式還存在一個問題就是當 A 節點故障後,B 節點無法取到 A 節點中還未消費的消息實體。
- 如果做了消息持久化,那麼得等 A 節點恢複,才可被消費;如果沒有持久化的話,消息會丢失。
鏡像模式
- 該模式解決了上述問題,其和普通模式不同之處在于,消息實體會主動在鏡像節點間同步,而不是在消費者取資料時臨時拉取。
- 該模式帶來的副作用也很明顯,除了降低系統性能外,如果鏡像隊列數量過多,加之大量的消息進入,叢集内部的網絡帶寬将會被這種同步通訊大大消耗掉。
- 是以,在對可靠性要求較高的場合中适用于該模式。
個人感覺,在生産環境中,還是使用鏡像模式比較保險。
要想使用鏡像模式,不管是通過管理頁面,還是指令行方式,隻需要簡單配置即可完成。管理頁面方式就不過多介紹了,下面說說如何通過指令行來設定,一條指令就搞定。
添加:
# rabbitmqctl set_policy -p testvhost testha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
Setting policy "testha" for pattern "^" to "{"ha-mode":"all","ha-sync-mode":"automatic"}" with priority "0" for vhost "testvhost" ...
複制
清除:
# rabbitmqctl clear_policy -p testvhost testha
Clearing policy "testha" on vhost "testvhost" ...
複制
檢視:
# rabbitmqctl list_policies -p testvhost
Listing policies for vhost "testvhost" ...
vhost name pattern apply-to definition priority
testvhost testha ^ all {"ha-mode":"all","ha-sync-mode":"automatic"} 0
複制
參數說明:
- Virtual host:政策應用的 vhost。
- Name:為政策名稱,可以是任何名稱,但建議使用不帶空格的基于 ASCII 的名稱。
- Pattern:與一個或多個 queue(exchange) 名稱比對的正規表達式,可以使用任何正規表達式。隻有一個
代表比對所有,^
為比對名稱為 "test" 的 exchanges 或者 queue。^test
- Apply to:Pattern 應用對象。
- Priority:配置多個政策時的優先級,值越大,優先級越高。沒有指定優先級的消息會以 0 優先級對待,對于超過隊列所定最大優先級的消息,優先級以最大優先級對待。
- Definition:鍵/值對,将被插入比對 queues and exchanges 的可選參數映射中。
:政策鍵,分為 3 種模式:ha-mode
-
:所有的 queue。all
-
:部分(需配置exctly
參數,此參數為 int 類型。比如 3,衆多叢集中的随機 3 台機器)。ha-params
-
:指定(需配置nodes
參數,此參數為數組類型。比如 ["rabbit@rabbit2", "rabbit@rabbit3"] 這樣指定為 rabbit2 與 rabbit3 這兩台機器)。ha-params
:隊列同步:ha-sync-mode
-
:手動(預設模式)。新的隊列鏡像将不會收到現有的消息,它隻會接收新的消息。manual
-
:自動同步。當一個新鏡像加入時,隊列會自動同步。隊列同步是一個阻塞操作。automatic
-
以上就是本篇全部内容,歡迎大家留言交流。
下一篇: Springcloud Eureka instance 配置項→