docker搭建RabbitMQ單機(jī)集群

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ù)用空格分割

  1. 參數(shù)一:名稱,可以隨便填;
  2. 參數(shù)二:隊(duì)列名稱的匹配規(guī)則,使用正則表達(dá)式表示;
  3. 參數(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)限

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容