0. 前言
實(shí)際生產(chǎn)應(yīng)用中都會(huì)采用消息隊(duì)列的集群方案,如果選擇RabbitMQ那么有必要了解下它的集群方案原理
一般來(lái)說(shuō),如果只是為了學(xué)習(xí)RabbitMQ或者驗(yàn)證業(yè)務(wù)工程的正確性那么在本地環(huán)境或者測(cè)試環(huán)境上使用其單實(shí)例部署就可以了,但是出于MQ中間件本身的可靠性、并發(fā)性、吞吐量和消息堆積能力等問(wèn)題的考慮,在生產(chǎn)環(huán)境上一般都會(huì)考慮使用RabbitMQ的集群方案。
1. 集群方案的原理
RabbitMQ這款消息隊(duì)列中間件產(chǎn)品本身是基于Erlang編寫,Erlang語(yǔ)言天生具備分布式特性(通過(guò)同步Erlang集群各節(jié)點(diǎn)的magic cookie來(lái)實(shí)現(xiàn))。因此,RabbitMQ天然支持Clustering。這使得RabbitMQ本身不需要像ActiveMQ、Kafka那樣通過(guò)ZooKeeper分別來(lái)實(shí)現(xiàn)HA方案和保存集群的元數(shù)據(jù)。集群是保證可靠性的一種方式,同時(shí)可以通過(guò)水平擴(kuò)展以達(dá)到增加消息吞吐量能力的目的。

由上圖可知,我們的集群需要一個(gè)HAProxy,HA是high available的意思,通過(guò)這個(gè)HAProxy去代理producer和consumer的請(qǐng)求。
2. 單機(jī)多實(shí)例部署
由于某些因素的限制,有時(shí)候你不得不在一臺(tái)機(jī)器上去搭建一個(gè)rabbitmq集群,這個(gè)有點(diǎn)類似zookeeper的單機(jī)版。真實(shí)生成環(huán)境還是要配成多機(jī)集群的。有關(guān)怎么配置多機(jī)集群的可以參考其他的資料,這里主要論述如何在單機(jī)中配置多個(gè)rabbitmq實(shí)例。
2.1 回顧docker創(chuàng)建單個(gè)rabbitmq服務(wù)的過(guò)程
服務(wù)器上執(zhí)行
ubuntu@VM-0-8-ubuntu:~$ docker exec -it 47b /bin/bash
進(jìn)入rabbitmq容器,首先確保RabbitMQ運(yùn)行沒(méi)有問(wèn)題
root@47b96c4e50ef:/# rabbitmqctl status
我們就將其定義為第一個(gè)結(jié)點(diǎn)
回顧一下這個(gè)結(jié)點(diǎn)創(chuàng)建的命令
docker run --name rabbitmq -d -p 15672:15672 -p 5672:5672 263c941f71ea
263c941f71ea是我rabbitmq(tag為3.8-management)鏡像id,
2.2 docker搭建RabbitMQ集群
創(chuàng)建結(jié)點(diǎn)
docker run -d --hostname rabbit1 --name rabbit1 -p 15672:15672 -p 5672:5672 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:3.8-management
docker run -d --hostname rabbit2 --name rabbit2 -p 5673:5672 --link rabbit1:rabbit1 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:3.8-management
docker run -d --hostname rabbit3 --name rabbit3 -p 5674:5672 --link rabbit1:rabbit1 --link rabbit2:rabbit2 -e RABBITMQ_ERLANG_COOKIE='rabbitcookie' rabbitmq:3.8-management
這里解釋下 --hostname rabbit1 是指創(chuàng)建后集群內(nèi)的第一個(gè)節(jié)點(diǎn)名為rabbit1, --name 是容器名 ,使用–link 進(jìn)行容器之間互連,link不可或缺,使得三個(gè)容器能互相通信
Erlang Cookie
有些特殊的情況,比如已經(jīng)運(yùn)行了一段時(shí)間的幾個(gè)單個(gè)物理機(jī),我們?cè)谥皼](méi)有設(shè)置過(guò)相同的Erlang Cookie值,現(xiàn)在我們要把單個(gè)的物理機(jī)部署成集群,實(shí)現(xiàn)我們需要同步Erlang的Cookie值。
1.為什么要配置相同的erlang cookie?
因?yàn)镽abbitMQ是用Erlang實(shí)現(xiàn)的,Erlang Cookie相當(dāng)于不同節(jié)點(diǎn)之間相互通訊的秘鑰,Erlang節(jié)點(diǎn)通過(guò)交換Erlang Cookie獲得認(rèn)證。
2.Erlang Cookie的位置
默認(rèn)情況下,文件在
/var/lib/rabbitmq/.erlang.cookie。
進(jìn)入容器配置
設(shè)置結(jié)點(diǎn)1
docker exec -it rabbit1 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl start_app
exit
設(shè)置節(jié)點(diǎn)2,加入到集群:
docker exec -it rabbit2 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbit1
rabbitmqctl start_app
exit
設(shè)置節(jié)點(diǎn)3,加入到集群:
docker exec -it rabbit3 bash
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster --ram rabbit@rabbit1
rabbitmqctl start_app
exit
其中,參數(shù)“--ram”表示設(shè)置為內(nèi)存節(jié)點(diǎn),忽略次參數(shù)默認(rèn)為磁盤節(jié)點(diǎn)。在輸入命令的時(shí)候會(huì)有下列的提示,docker run 的時(shí)候加入RABBITMQ_ERLANG_COOKIE的方法未來(lái)會(huì)被移除,建議下面兩種方法代替。
RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead.
配置好后,打開web控制臺(tái)可以看到如下集群,我們啟動(dòng)了3個(gè)節(jié)點(diǎn),1個(gè)磁盤節(jié)點(diǎn)和2個(gè)內(nèi)存節(jié)點(diǎn)。

配置RABBITMQ_ERLANG_COOKIE,保持一致
輸入docker ps查看rabbit1容器id,
運(yùn)行docker logs bbaab774d75e命令查看rabbit1的logs找到home dir

我們知道這是容器1的目錄,接下來(lái)把這個(gè)文件夾都拷貝出來(lái)后復(fù)制給其他容器:
物理機(jī)和容器之間復(fù)制命令如下:
- 容器復(fù)制文件到物理機(jī):docker cp 容器名稱:容器目錄 物理機(jī)目錄
- 物理機(jī)復(fù)制文件到容器:docker cp 物理機(jī)目錄 容器名稱:容器目錄
首先建立主機(jī)目錄,我這里建立了一個(gè)文件夾/home/ubuntu/copy_dir(我這里用戶目錄就是/home/ubuntu/)
對(duì)于rabbit1的容器ID,執(zhí)行docker cp 容器ID:/var/lib/rabbitmq/. 主機(jī)目錄:
ubuntu@VM-0-8-ubuntu:~$ docker cp bbaab774d75e:/var/lib/rabbitmq/. /home/ubuntu/copy_dir
ubuntu@VM-0-8-ubuntu:~$ cd copy_dir/ && ls -a
. .. .bash_history .erlang.cookie mnesia
進(jìn)入主機(jī)目錄輸入ls -a可以看到一個(gè)隱藏的文件.erlang.cookie,把它拷貝到其他容器中,即對(duì)于myrabbit2 , myrabbit3的容器,執(zhí)行docker cp 主機(jī)目錄/.erlang.cookie 容器ID:/var/lib/rabbitmq/:
docker cp /home/ubuntu/copy_dir/.erlang.cookie 1a2929c26883:/var/lib/rabbitmq/
docker cp /home/ubuntu/copy_dir/.erlang.cookie edc76e910a0c:/var/lib/rabbitmq/
查看集群狀態(tài)
進(jìn)入rabbit1,查看集群狀態(tài)
ubuntu@VM-0-8-ubuntu:~/copy_dir$ docker exec -it bba bash
root@rabbit1:/# rabbitmqctl cluster_status
RABBITMQ_ERLANG_COOKIE env variable support is deprecated and will be REMOVED in a future version. Use the $HOME/.erlang.cookie file or the --erlang-cookie switch instead.
Cluster status of node rabbit@rabbit1 ...
Basics
Cluster name: rabbit@rabbit1
Disk Nodes
rabbit@rabbit1
RAM Nodes
rabbit@rabbit2
rabbit@rabbit3
Running Nodes
rabbit@rabbit1
rabbit@rabbit2
rabbit@rabbit3
Versions
rabbit@rabbit1: RabbitMQ 3.8.9 on Erlang 23.1.4
rabbit@rabbit2: on Erlang
rabbit@rabbit3: on Erlang
... ...
... ...
到此為止,我們已經(jīng)完成了RabbitMQ集群的建立,啟動(dòng)了3個(gè)節(jié)點(diǎn),1個(gè)磁盤節(jié)點(diǎn)和2個(gè)內(nèi)存節(jié)點(diǎn)。
2.3 集群管理
rabbitmqctl join_cluster {cluster_node} [–ram]
將節(jié)點(diǎn)加入指定集群中。在這個(gè)命令執(zhí)行前需要停止RabbitMQ應(yīng)用并重置節(jié)點(diǎn)。
rabbitmqctl cluster_status
顯示集群的狀態(tài)。
rabbitmqctl change_cluster_node_type {disc|ram}
修改集群節(jié)點(diǎn)的類型。在這個(gè)命令執(zhí)行前需要停止RabbitMQ應(yīng)用。
rabbitmqctl forget_cluster_node [–offline]
將節(jié)點(diǎn)從集群中刪除,允許離線執(zhí)行。
rabbitmqctl update_cluster_nodes {clusternode}
在集群中的節(jié)點(diǎn)應(yīng)用啟動(dòng)前咨詢clusternode節(jié)點(diǎn)的最新信息,并更新相應(yīng)的集群信息。這個(gè)和join_cluster不同,它不加入集群??紤]這樣一種情況,節(jié)點(diǎn)A和節(jié)點(diǎn)B都在集群中,當(dāng)節(jié)點(diǎn)A離線了,節(jié)點(diǎn)C又和節(jié)點(diǎn)B組成了一個(gè)集群,然后節(jié)點(diǎn)B又離開了集群,當(dāng)A醒來(lái)的時(shí)候,它會(huì)嘗試聯(lián)系節(jié)點(diǎn)B,但是這樣會(huì)失敗,因?yàn)楣?jié)點(diǎn)B已經(jīng)不在集群中了。
rabbitmqctl cancel_sync_queue [-p vhost] {queue}
取消隊(duì)列queue同步鏡像的操作。
rabbitmqctl set_cluster_name {name}
設(shè)置集群名稱。集群名稱在客戶端連接時(shí)會(huì)通報(bào)給客戶端。Federation和Shovel插件也會(huì)有用到集群名稱的地方。集群名稱默認(rèn)是集群中第一個(gè)節(jié)點(diǎn)的名稱,通過(guò)這個(gè)命令可以重新設(shè)置。
設(shè)置節(jié)點(diǎn)類型
如果你想更換節(jié)點(diǎn)類型可以通過(guò)命令修改,如下:
rabbitmqctl stop_app
rabbitmqctl change_cluster_node_type dist
rabbitmqctl change_cluster_node_type ram
rabbitmqctl start_app
移除節(jié)點(diǎn)
如果想要把節(jié)點(diǎn)從集群中移除,可使用如下命令實(shí)現(xiàn):
rabbitmqctl stop_app
rabbitmqctl restart
rabbitmqctl start_app
集群重啟順序
集群重啟的順序是固定的,并且是相反的。如下所述:
- 啟動(dòng)順序:磁盤節(jié)點(diǎn) => 內(nèi)存節(jié)點(diǎn)
- 關(guān)閉順序:內(nèi)存節(jié)點(diǎn) => 磁盤節(jié)點(diǎn)
最后關(guān)閉必須是磁盤節(jié)點(diǎn),不然可能回造成集群?jiǎn)?dòng)失敗、數(shù)據(jù)丟失等異常情況
2.4 鏡像隊(duì)列完成HA
鏡像隊(duì)列是Rabbit2.6.0版本帶來(lái)的一個(gè)新功能,允許內(nèi)建雙活冗余選項(xiàng),與普通隊(duì)列不同,鏡像節(jié)點(diǎn)在集群中的其他節(jié)點(diǎn)擁有從隊(duì)列拷貝,一旦主節(jié)點(diǎn)不可用,最老的從隊(duì)列將被選舉為新的主隊(duì)列。
鏡像隊(duì)列的工作原理:在某種程度上你可以將鏡像隊(duì)列視為,擁有一個(gè)隱藏的fanout交換器,它指示者信道將消息分發(fā)到從隊(duì)列上。
上面已經(jīng)完成RabbitMQ默認(rèn)集群模式,但并不保證隊(duì)列的高可用性,盡管交換機(jī)、綁定這些可以復(fù)制到集群里的任何一個(gè)節(jié)點(diǎn),但是隊(duì)列內(nèi)容不會(huì)復(fù)制。雖然該模式解決一項(xiàng)目組節(jié)點(diǎn)壓力,但隊(duì)列節(jié)點(diǎn)宕機(jī)直接導(dǎo)致該隊(duì)列無(wú)法應(yīng)用,只能等待重啟,所以要想在隊(duì)列節(jié)點(diǎn)宕機(jī)或故障也能正常應(yīng)用,就要復(fù)制隊(duì)列內(nèi)容到集群里的每個(gè)節(jié)點(diǎn),必須要?jiǎng)?chuàng)建鏡像隊(duì)列。
鏡像隊(duì)列是基于普通的集群模式的,然后再添加一些策略,所以你還是得先配置普通集群,然后才能設(shè)置鏡像隊(duì)列,我們就以上面的集群接著做。
先進(jìn)入rabbit1,新增一個(gè)用戶名和密碼,guest可能會(huì)出現(xiàn)問(wèn)題
# 先添加個(gè)用戶
rabbitmqctl add_user 新用戶名 新密碼
# 然后可以選擇把原來(lái)那個(gè)刪了
# rabbitmqctl delete_user 原來(lái)的用戶名,即guest
# 查看用戶組,發(fā)現(xiàn)新增用戶沒(méi)有權(quán)限,TAG=[]
rabbitmqctl list_users
# 賦予root用戶所有權(quán)限
rabbitmqctl set_permissions -p / root ".*" ".*" ".*"
# 賦予root用戶administrator角色
rabbitmqctl set_user_tags root administrator
# 再次查看用戶組
rabbitmqctl list_users
# 顯示
Listing users ...
user tags
guest [administrator]
root [administrator]
設(shè)置的鏡像隊(duì)列可以通過(guò)開啟的網(wǎng)頁(yè)的管理端Admin->Policies,也可以通過(guò)命令。
rabbitmqctl set_policy my_ha "^" '{"ha-mode":"all"}'
通過(guò)web控制臺(tái)配置鏡像隊(duì)列

- Name: 策略名稱
- Pattern: 匹配的規(guī)則,如果是匹配所有的隊(duì)列,是^.
- Definition: 使用ha-mode模式中的all,也就是同步所有匹配的隊(duì)列,ha-sync-mode 表示設(shè)置節(jié)點(diǎn)間隊(duì)列數(shù)據(jù)同步,如果不設(shè)置會(huì)出現(xiàn)不同步。問(wèn)號(hào)鏈接幫助文檔。
當(dāng)你完成了這一步,那么恭喜你完成了高可用,如果一個(gè)或者兩個(gè)節(jié)點(diǎn)掉了,第三個(gè)節(jié)點(diǎn)也能完成數(shù)據(jù)接收,在前兩個(gè)節(jié)點(diǎn)恢復(fù)后,第三個(gè)節(jié)點(diǎn)也能迅速地同步數(shù)據(jù)到前兩個(gè)節(jié)點(diǎn)。
ha-sync-mode : 如果 此節(jié)點(diǎn) 不進(jìn)行設(shè)置 ,在其中一臺(tái) 服務(wù)器 宕機(jī) 再 啟動(dòng) 后 會(huì)報(bào) Unsynchronised Mirrors XXXX 錯(cuò)誤。
這時(shí)候 在 隊(duì)列詳細(xì)信息 頁(yè)面 需要 手動(dòng) 點(diǎn)擊 同步隊(duì)列 或者 用命令行 執(zhí)行 命令 rabbitmqctl sync_queue name

如果看到這樣的隊(duì)列,我們已經(jīng)完成了 RabbitMQ 集群鏡像隊(duì)列的高可用性配置。集群中任意一臺(tái)宕機(jī)都會(huì)自動(dòng)切換到另一臺(tái)宕機(jī)機(jī)器開啟時(shí)會(huì)自動(dòng)同步鏡像隊(duì)列,使其保持一致。
其中+2的意思是有三個(gè)節(jié)點(diǎn),一個(gè)節(jié)點(diǎn)本身和兩個(gè)鏡像節(jié)點(diǎn)。
通過(guò)命令行控制鏡像隊(duì)列
rabbitmqctl set_policy my_ha "^" '{"ha-mode":"all","ha-sync-mode":"automatic"}'
可以看出設(shè)置鏡像隊(duì)列,一共有三個(gè)參數(shù),每個(gè)參數(shù)用空格分割。
- 參數(shù)一:名稱,可以隨便填;
- 參數(shù)二:隊(duì)列名稱的匹配規(guī)則,使用正則表達(dá)式表示;
- 參數(shù)三:為鏡像隊(duì)列的主體規(guī)則,是json字符串,分為三個(gè)屬性:ha-mode | ha-params | ha-sync-mode,分別的解釋如下:
ha-mode:鏡像模式,分類:all/exactly/nodes,all存儲(chǔ)在所有節(jié)點(diǎn);exactly存儲(chǔ)x個(gè)節(jié)點(diǎn),節(jié)點(diǎn)的個(gè)數(shù)由ha-params指定;nodes指定存儲(chǔ)的節(jié)點(diǎn)上名稱,通過(guò)ha-params指定;
ha-params:作為參數(shù),為ha-mode的補(bǔ)充;
ha-sync-mode:鏡像消息同步方式:automatic(自動(dòng)),manually(手動(dòng));
查看鏡像隊(duì)列
rabbitmqctl list_policies
刪除鏡像隊(duì)列
rabbitmqctl clear_policy
3. 負(fù)載均衡-HAProxy
搭建完鏡像隊(duì)列,其實(shí)還有點(diǎn)問(wèn)題,我們節(jié)點(diǎn)1掛了,控制臺(tái)就打不開了,當(dāng)然,可能是因?yàn)楣?jié)點(diǎn)一開始run的時(shí)候沒(méi)有設(shè)置
HAProxy提供高可用性、負(fù)載均衡以及基于TCP和HTTP應(yīng)用的代理,支持虛擬主機(jī),它是免費(fèi)、快速并且可靠的一種解決方案,包括Twitter,Reddit,StackOverflow,GitHub在內(nèi)的多家知名互聯(lián)網(wǎng)公司在使用。HAProxy實(shí)現(xiàn)了一種事件驅(qū)動(dòng)、單一進(jìn)程模型,此模型支持非常大的并發(fā)連接數(shù)。
3.1 設(shè)置rabbitmqnet
ubuntu@VM-0-8-ubuntu:~/haproxy$ docker network create rabbitmqnet
ubuntu@VM-0-8-ubuntu:~/haproxy$ docker network connect rabbitmqnet rabbit1
ubuntu@VM-0-8-ubuntu:~/haproxy$ docker network connect rabbitmqnet rabbit2
ubuntu@VM-0-8-ubuntu:~/haproxy$ docker network connect rabbitmqnet rabbit3
3.2 查看該網(wǎng)絡(luò)情況
查看rabbitmqnet的網(wǎng)絡(luò)情況,可以看到我的3個(gè)rabbit加入這個(gè)網(wǎng)絡(luò)是127.21.0.0/16
ubuntu@VM-0-8-ubuntu:~/haproxy$ docker network inspect rabbitmqnet
[
{
"Name": "rabbitmqnet",
"Id": "21071d91f6b5150072e55628d90ca78542529cc4a48cd0cb08d44687cec9b99d",
"Created": "2020-12-09T23:59:38.92208807+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.21.0.0/16",
"Gateway": "172.21.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"1a2929c26883bfccb1794d556201bdd7c3462b1629615d802121587d7a7cc390": {
"Name": "rabbit2",
"EndpointID": "f7bff6d9b49187ec7ec7500bcbd725eb39c743f032886d7e97baf2fb82b48177",
"MacAddress": "02:42:ac:15:00:03",
"IPv4Address": "172.21.0.3/16",
"IPv6Address": ""
},
"6f99f26d8d8a928d7faea94b682c19ebd72af523b7f9a229e6ce12acd5efcc4a": {
"Name": "haproxy",
"EndpointID": "dfc610fba529a2b30218a27eaa02f56de569f0c21eb952445c3bc51d215b0b8a",
"MacAddress": "02:42:ac:15:00:05",
"IPv4Address": "172.21.0.5/16",
"IPv6Address": ""
},
"bbaab774d75e34bd479982cc5791a5a7e7447b02b86cf7b7388b41c356f0c364": {
"Name": "rabbit1",
"EndpointID": "70f9ada99b683722ec3889ae5920e2ba3c66a99d64551aaa69a17856353b5e67",
"MacAddress": "02:42:ac:15:00:02",
"IPv4Address": "172.21.0.2/16",
"IPv6Address": ""
},
"edc76e910a0c55eaf3ed2587420bade7c79da13a7f45e098214ad4dcdf53a718": {
"Name": "rabbit3",
"EndpointID": "e63966a7f727db36aa2b5ea7c831c1cf9d853a55d1662cefdc8a0e24d9b9bbd5",
"MacAddress": "02:42:ac:15:00:04",
"IPv4Address": "172.21.0.4/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
3.3 配置haproxy.cfg
在/home/ubuntu/haproxy/下vi haproxy.cfg,配置haproxy,在失敗了很多次之后,終于找到了一個(gè)解決辦法,就是直接綁定這個(gè)網(wǎng)絡(luò)的私有ip,參考了https://blog.csdn.net/fqydhk/article/details/80430503這篇文章
global
maxconn 10000 #默認(rèn)最大連接數(shù)
log 127.0.0.1 local0 #[err warning info debug]
chroot /usr/local/sbin #chroot運(yùn)行的路徑
daemon #以后臺(tái)形式運(yùn)行haproxy
pidfile /var/run/haproxy.pid #haproxy的pid存放路徑,啟動(dòng)進(jìn)程的用戶必須有權(quán)限訪問(wèn)此文件
defaults
log 127.0.0.1 local3
mode http #所處理的類別 (#7層 http;4層tcp )
maxconn 10000 #最大連接數(shù)
option dontlognull #不記錄健康檢查的日志信息
option redispatch #serverId對(duì)應(yīng)的服務(wù)器掛掉后,強(qiáng)制定向到其他健康的服務(wù)器
#stats refresh 30 #統(tǒng)計(jì)頁(yè)面刷新間隔
retries 3 #3次連接失敗就認(rèn)為服務(wù)不可用,也可以通過(guò)后面設(shè)置
balance roundrobin #默認(rèn)的負(fù)載均衡的方式,輪詢方式
#balance source #默認(rèn)的負(fù)載均衡的方式,類似nginx的ip_hash
#balance leastconn #默認(rèn)的負(fù)載均衡的方式,最小連接
timeout connect 5000 #連接超時(shí)
timeout client 50000 #客戶端超時(shí)
timeout server 50000 #服務(wù)器超時(shí)
timeout check 2000 #心跳檢測(cè)超時(shí)
####################################################################
listen http_front
bind 0.0.0.0:5669 #監(jiān)聽端口
stats refresh 30s #統(tǒng)計(jì)頁(yè)面自動(dòng)刷新時(shí)間
stats uri /haproxy?stats #統(tǒng)計(jì)頁(yè)面url
stats realm Haproxy Manager #統(tǒng)計(jì)頁(yè)面密碼框上提示文本
stats auth admin:admin #統(tǒng)計(jì)頁(yè)面用戶名和密碼設(shè)置
#stats hide-version #隱藏統(tǒng)計(jì)頁(yè)面上HAProxy的版本信息
#####################我把RabbitMQ的管理界面也放在HAProxy后面了###############################
listen rabbitmq_admin
bind 0.0.0.0:5671
server rabbitmq3 172.21.0.4:15674
server rabbitmq2 172.21.0.3:15673
server rabbitmq1 172.21.0.2:15672
####################################################################
listen rabbitmq_cluster
bind 0.0.0.0:5670
option tcplog
mode tcp
timeout client 3h
timeout server 3h
option clitcpka
balance roundrobin #負(fù)載均衡算法(#banlance roundrobin 輪詢,balance source 保存session值,支持static-rr,leastconn,first,uri等參數(shù))
#balance url_param userid
#balance url_param session_id check_post 64
#balance hdr(User-Agent)
#balance hdr(host)
#balance hdr(Host) use_domain_only
#balance rdp-cookie
#balance leastconn
#balance source //ip
server rabbitmq3 172.21.0.4:5674 check inter 5s rise 2 fall 3 #check inter 2000 是檢測(cè)心跳頻率,rise 2是2次正確認(rèn)為服務(wù)器可用,fall 3是3次失敗認(rèn)為服務(wù)器不可用
server rabbitmq2 172.21.0.3:5673 check inter 5s rise 2 fall 3
server rabbitmq1 172.21.0.2:5672 check inter 5s rise 2 fall 3
3.4 創(chuàng)建haproxy容器
創(chuàng)建容器,綁定外部和內(nèi)部的5669-5671端口
docker run -d -p 5669-5671:5669-5671 \
-v /home/ubuntu/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg \
--name=haproxy \
--net=rabbitmqnet \
haproxy
3.5 查看haproxy控制臺(tái)
輸入{主機(jī)ip}:5669/haproxy?stats,可以看到haproxy的控制臺(tái),大功告成!

3.6查看rabbitmq的web控制臺(tái)
{主機(jī)ip}:5671,登陸,是熟悉的界面

3.7 代碼測(cè)試
代碼中訪問(wèn)mq集群地址,則變?yōu)樵L問(wèn)haproxy地址:5670
#配置RabbitMQ的基本信息 ip 端口 username password
spring:
rabbitmq:
host: asjunor.site
port: 5670
username: xxx
password: xxx
virtual-host: /example
復(fù)用原來(lái)的代碼,修改applicationn.yml,將端口改為5670,發(fā)一條消息來(lái)測(cè)試能否使用集群。
如果出現(xiàn)以下錯(cuò)誤:
An unexpected connection driver error occured (Exception message: Socket closed)
有可能是你的用戶權(quán)限問(wèn)題,在web控制端修改權(quán)限
