RabbitMQ部署指南
1.單機(jī)部署
我們在Centos7虛擬機(jī)中使用Docker來安裝埃脏。
1.1.下載鏡像
方式一:在線拉取
docker pull rabbitmq:3.8-management
方式二:從本地加載
在課前資料已經(jīng)提供了鏡像包:
上傳到虛擬機(jī)中后,使用命令加載鏡像即可:
docker load -i mq.tar
1.2.安裝MQ
執(zhí)行下面的命令來運(yùn)行MQ容器:
docker run \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
-v mq-plugins:/plugins \
--name mq \
--hostname mq1 \
-p 15672:15672 \
-p 5672:5672 \
-d \
rabbitmq:3.8-management
2.安裝DelayExchange插件
官方的安裝指南地址為:https://blog.rabbitmq.com/posts/2015/04/scheduling-messages-with-rabbitmq
上述文檔是基于linux原生安裝RabbitMQ秋忙,然后安裝插件彩掐。
因為我們之前是基于Docker安裝RabbitMQ,所以下面我們會講解基于Docker來安裝RabbitMQ插件灰追。
2.1.下載插件
RabbitMQ有一個官方的插件社區(qū)堵幽,地址為:https://www.rabbitmq.com/community-plugins.html
其中包含各種各樣的插件,包括我們要使用的DelayExchange插件:
大家可以去對應(yīng)的GitHub頁面下載3.8.9版本的插件弹澎,地址為https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/tag/3.8.9這個對應(yīng)RabbitMQ的3.8.5以上版本朴下。
課前資料也提供了下載好的插件:
2.2.上傳插件
因為我們是基于Docker安裝,所以需要先查看RabbitMQ的插件目錄對應(yīng)的數(shù)據(jù)卷苦蒿。如果不是基于Docker的同學(xué)殴胧,請參考第一章部分,重新創(chuàng)建Docker容器佩迟。
我們之前設(shè)定的RabbitMQ的數(shù)據(jù)卷名稱為mq-plugins
团滥,所以我們使用下面命令查看數(shù)據(jù)卷:
docker volume inspect mq-plugins
可以得到下面結(jié)果:
接下來,將插件上傳到這個目錄即可:
2.3.安裝插件
最后就是安裝了报强,需要進(jìn)入MQ容器內(nèi)部來執(zhí)行安裝灸姊。我的容器名為mq
,所以執(zhí)行下面命令:
docker exec -it mq bash
執(zhí)行時躺涝,請將其中的 -it
后面的mq
替換為你自己的容器名.
進(jìn)入容器內(nèi)部后厨钻,執(zhí)行下面命令開啟插件:
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
結(jié)果如下:
3.集群部署
接下來扼雏,我們看看如何安裝RabbitMQ的集群。
3.1.集群分類
在RabbitMQ的官方文檔中夯膀,講述了兩種集群的配置方式:
- 普通模式:普通模式集群不進(jìn)行數(shù)據(jù)同步诗充,每個MQ都有自己的隊列、數(shù)據(jù)信息(其它元數(shù)據(jù)信息如交換機(jī)等會同步)诱建。例如我們有2個MQ:mq1蝴蜓,和mq2,如果你的消息在mq1俺猿,而你連接到了mq2茎匠,那么mq2會去mq1拉取消息,然后返回給你押袍。如果mq1宕機(jī)诵冒,消息就會丟失亩进。
- 鏡像模式:與普通模式不同礁蔗,隊列會在各個mq的鏡像節(jié)點(diǎn)之間同步交惯,因此你連接到任何一個鏡像節(jié)點(diǎn)蜡峰,均可獲取到消息。而且如果一個節(jié)點(diǎn)宕機(jī)囤屹,并不會導(dǎo)致數(shù)據(jù)丟失氏豌。不過台诗,這種方式增加了數(shù)據(jù)同步的帶寬消耗驱敲。
我們先來看普通模式集群铁蹈,我們的計劃部署3節(jié)點(diǎn)的mq集群:
主機(jī)名 | 控制臺端口 | amqp通信端口 |
---|---|---|
mq1 | 8081 ---> 15672 | 8071 ---> 5672 |
mq2 | 8082 ---> 15672 | 8072 ---> 5672 |
mq3 | 8083 ---> 15672 | 8073 ---> 5672 |
集群中的節(jié)點(diǎn)標(biāo)示默認(rèn)都是:rabbit@[hostname]
,因此以上三個節(jié)點(diǎn)的名稱分別為:
- rabbit@mq1
- rabbit@mq2
- rabbit@mq3
3.2.獲取cookie
RabbitMQ底層依賴于Erlang众眨,而Erlang虛擬機(jī)就是一個面向分布式的語言握牧,默認(rèn)就支持集群模式。集群模式中的每個RabbitMQ 節(jié)點(diǎn)使用 cookie 來確定它們是否被允許相互通信围辙。
要使兩個節(jié)點(diǎn)能夠通信我碟,它們必須具有相同的共享秘密,稱為Erlang cookie姚建。cookie 只是一串最多 255 個字符的字母數(shù)字字符。
每個集群節(jié)點(diǎn)必須具有相同的 cookie吱殉。實例之間也需要它來相互通信掸冤。
我們先在之前啟動的mq容器中獲取一個cookie值,作為集群的cookie友雳。執(zhí)行下面的命令:
docker exec -it mq cat /var/lib/rabbitmq/.erlang.cookie
可以看到cookie值如下:
FXZMCVGLBIXZCDEMMVZQ
接下來稿湿,停止并刪除當(dāng)前的mq容器,我們重新搭建集群押赊。
docker rm -f mq
3.3.準(zhǔn)備集群配置
在/tmp目錄新建一個配置文件 rabbitmq.conf:
cd /tmp
# 創(chuàng)建文件
touch rabbitmq.conf
文件內(nèi)容如下:
loopback_users.guest = false
listeners.tcp.default = 5672
cluster_formation.peer_discovery_backend = rabbit_peer_discovery_classic_config
cluster_formation.classic_config.nodes.1 = rabbit@mq1
cluster_formation.classic_config.nodes.2 = rabbit@mq2
cluster_formation.classic_config.nodes.3 = rabbit@mq3
再創(chuàng)建一個文件饺藤,記錄cookie
cd /tmp
# 創(chuàng)建cookie文件
touch .erlang.cookie
# 寫入cookie
echo "FXZMCVGLBIXZCDEMMVZQ" > .erlang.cookie
# 修改cookie文件的權(quán)限
chmod 600 .erlang.cookie
準(zhǔn)備三個目錄,mq1、mq2、mq3:
cd /tmp
# 創(chuàng)建目錄
mkdir mq1 mq2 mq3
然后拷貝rabbitmq.conf涕俗、cookie文件到mq1罗丰、mq2、mq3:
# 進(jìn)入/tmp
cd /tmp
# 拷貝
cp rabbitmq.conf mq1
cp rabbitmq.conf mq2
cp rabbitmq.conf mq3
cp .erlang.cookie mq1
cp .erlang.cookie mq2
cp .erlang.cookie mq3
3.4.啟動集群
創(chuàng)建一個網(wǎng)絡(luò):
docker network create mq-net
docker volume create
運(yùn)行命令
docker run -d --net mq-net \
-v ${PWD}/mq1/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq1 \
--hostname mq1 \
-p 8071:5672 \
-p 8081:15672 \
rabbitmq:3.8-management
docker run -d --net mq-net \
-v ${PWD}/mq2/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq2 \
--hostname mq2 \
-p 8072:5672 \
-p 8082:15672 \
rabbitmq:3.8-management
docker run -d --net mq-net \
-v ${PWD}/mq3/rabbitmq.conf:/etc/rabbitmq/rabbitmq.conf \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq3 \
--hostname mq3 \
-p 8073:5672 \
-p 8083:15672 \
rabbitmq:3.8-management
3.5.測試
在mq1這個節(jié)點(diǎn)上添加一個隊列:
如圖再姑,在mq2和mq3兩個控制臺也都能看到:
3.5.1.數(shù)據(jù)共享測試
點(diǎn)擊這個隊列萌抵,進(jìn)入管理頁面:
然后利用控制臺發(fā)送一條消息到這個隊列:
結(jié)果在mq2、mq3上都能看到這條消息:
3.5.2.可用性測試
我們讓其中一臺節(jié)點(diǎn)mq1宕機(jī):
docker stop mq1
然后登錄mq2或mq3的控制臺元镀,發(fā)現(xiàn)simple.queue也不可用了:
說明數(shù)據(jù)并沒有拷貝到mq2和mq3绍填。
4.鏡像模式
在剛剛的案例中,一旦創(chuàng)建隊列的主機(jī)宕機(jī)栖疑,隊列就會不可用讨永。不具備高可用能力。如果要解決這個問題遇革,必須使用官方提供的鏡像集群方案住闯。
官方文檔地址:https://www.rabbitmq.com/ha.html
4.1.鏡像模式的特征
默認(rèn)情況下,隊列只保存在創(chuàng)建該隊列的節(jié)點(diǎn)上澳淑。而鏡像模式下比原,創(chuàng)建隊列的節(jié)點(diǎn)被稱為該隊列的主節(jié)點(diǎn),隊列還會拷貝到集群中的其它節(jié)點(diǎn)杠巡,也叫做該隊列的鏡像節(jié)點(diǎn)量窘。
但是,不同隊列可以在集群中的任意節(jié)點(diǎn)上創(chuàng)建氢拥,因此不同隊列的主節(jié)點(diǎn)可以不同蚌铜。甚至,一個隊列的主節(jié)點(diǎn)可能是另一個隊列的鏡像節(jié)點(diǎn)嫩海。
用戶發(fā)送給隊列的一切請求冬殃,例如發(fā)送消息、消息回執(zhí)默認(rèn)都會在主節(jié)點(diǎn)完成叁怪,如果是從節(jié)點(diǎn)接收到請求审葬,也會路由到主節(jié)點(diǎn)去完成。鏡像節(jié)點(diǎn)僅僅起到備份數(shù)據(jù)作用奕谭。
當(dāng)主節(jié)點(diǎn)接收到消費(fèi)者的ACK時涣觉,所有鏡像都會刪除節(jié)點(diǎn)中的數(shù)據(jù)。
總結(jié)如下:
- 鏡像隊列結(jié)構(gòu)是一主多從(從就是鏡像)
- 所有操作都是主節(jié)點(diǎn)完成血柳,然后同步給鏡像節(jié)點(diǎn)
- 主宕機(jī)后官册,鏡像節(jié)點(diǎn)會替代成新的主(如果在主從同步完成前,主就已經(jīng)宕機(jī)难捌,可能出現(xiàn)數(shù)據(jù)丟失)
- 不具備負(fù)載均衡功能膝宁,因為所有操作都會有主節(jié)點(diǎn)完成(但是不同隊列鸦难,其主節(jié)點(diǎn)可以不同,可以利用這個提高吞吐量)
4.2.鏡像模式的配置
鏡像模式的配置有3種模式:
ha-mode | ha-params | 效果 |
---|---|---|
準(zhǔn)確模式exactly | 隊列的副本量count | 集群中隊列副本(主服務(wù)器和鏡像服務(wù)器之和)的數(shù)量员淫。count如果為1意味著單個副本:即隊列主節(jié)點(diǎn)合蔽。count值為2表示2個副本:1個隊列主和1個隊列鏡像。換句話說:count = 鏡像數(shù)量 + 1满粗。如果群集中的節(jié)點(diǎn)數(shù)少于count辈末,則該隊列將鏡像到所有節(jié)點(diǎn)。如果有集群總數(shù)大于count+1映皆,并且包含鏡像的節(jié)點(diǎn)出現(xiàn)故障挤聘,則將在另一個節(jié)點(diǎn)上創(chuàng)建一個新的鏡像。 |
all | (none) | 隊列在群集中的所有節(jié)點(diǎn)之間進(jìn)行鏡像捅彻。隊列將鏡像到任何新加入的節(jié)點(diǎn)组去。鏡像到所有節(jié)點(diǎn)將對所有群集節(jié)點(diǎn)施加額外的壓力,包括網(wǎng)絡(luò)I / O步淹,磁盤I / O和磁盤空間使用情況从隆。推薦使用exactly,設(shè)置副本數(shù)為(N / 2 +1)缭裆。 |
nodes | node names | 指定隊列創(chuàng)建到哪些節(jié)點(diǎn)键闺,如果指定的節(jié)點(diǎn)全部不存在,則會出現(xiàn)異常澈驼。如果指定的節(jié)點(diǎn)在集群中存在辛燥,但是暫時不可用,會創(chuàng)建節(jié)點(diǎn)到當(dāng)前客戶端連接到的節(jié)點(diǎn)缝其。 |
這里我們以rabbitmqctl命令作為案例來講解配置語法挎塌。
語法示例:
4.2.1.exactly模式
rabbitmqctl set_policy ha-two "^two\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
-
rabbitmqctl set_policy
:固定寫法 -
ha-two
:策略名稱,自定義 -
"^two\."
:匹配隊列的正則表達(dá)式内边,符合命名規(guī)則的隊列才生效榴都,這里是任何以two.
開頭的隊列名稱 -
'{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
: 策略內(nèi)容-
"ha-mode":"exactly"
:策略模式,此處是exactly模式漠其,指定副本數(shù)量 -
"ha-params":2
:策略參數(shù)嘴高,這里是2,就是副本數(shù)量為2辉懒,1主1鏡像 -
"ha-sync-mode":"automatic"
:同步策略阳惹,默認(rèn)是manual,即新加入的鏡像節(jié)點(diǎn)不會同步舊的消息眶俩。如果設(shè)置為automatic,則新加入的鏡像節(jié)點(diǎn)會把主節(jié)點(diǎn)中所有消息都同步快鱼,會帶來額外的網(wǎng)絡(luò)開銷
-
4.2.2.all模式
rabbitmqctl set_policy ha-all "^all\." '{"ha-mode":"all"}'
-
ha-all
:策略名稱颠印,自定義 -
"^all\."
:匹配所有以all.
開頭的隊列名 -
'{"ha-mode":"all"}'
:策略內(nèi)容-
"ha-mode":"all"
:策略模式纲岭,此處是all模式,即所有節(jié)點(diǎn)都會稱為鏡像節(jié)點(diǎn)
-
4.2.3.nodes模式
rabbitmqctl set_policy ha-nodes "^nodes\." '{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
-
rabbitmqctl set_policy
:固定寫法 -
ha-nodes
:策略名稱线罕,自定義 -
"^nodes\."
:匹配隊列的正則表達(dá)式止潮,符合命名規(guī)則的隊列才生效,這里是任何以nodes.
開頭的隊列名稱 -
'{"ha-mode":"nodes","ha-params":["rabbit@nodeA", "rabbit@nodeB"]}'
: 策略內(nèi)容-
"ha-mode":"nodes"
:策略模式钞楼,此處是nodes模式 -
"ha-params":["rabbit@mq1", "rabbit@mq2"]
:策略參數(shù)喇闸,這里指定副本所在節(jié)點(diǎn)名稱
-
4.3.測試
我們使用exactly模式的鏡像,因為集群節(jié)點(diǎn)數(shù)量為3询件,因此鏡像數(shù)量就設(shè)置為2.
進(jìn)入到容器內(nèi)部運(yùn)行下面的命令:
docker exec -it mq1 rabbitmqctl set_policy ha-two "^two\." '{"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"}'
下面燃乍,我們創(chuàng)建一個新的隊列:
在任意一個mq控制臺查看隊列:
4.3.1.測試數(shù)據(jù)共享
給two.queue發(fā)送一條消息:
然后在mq1、mq2宛琅、mq3的任意控制臺查看消息:
4.3.2.測試高可用
現(xiàn)在刻蟹,我們讓two.queue的主節(jié)點(diǎn)mq1宕機(jī):
docker stop mq1
查看集群狀態(tài):
查看隊列狀態(tài):
發(fā)現(xiàn)依然是健康的!并且其主節(jié)點(diǎn)切換到了rabbit@mq2上
5.仲裁隊列
從RabbitMQ 3.8版本開始嘿辟,引入了新的仲裁隊列舆瘪,他具備與鏡像隊里類似的功能,但使用更加方便红伦。
5.1.添加仲裁隊列
在任意控制臺添加一個隊列英古,一定要選擇隊列類型為Quorum類型。
在任意控制臺查看隊列:
可以看到昙读,仲裁隊列的 + 2字樣召调。代表這個隊列有2個鏡像節(jié)點(diǎn)。
因為仲裁隊列默認(rèn)的鏡像數(shù)為5箕戳。如果你的集群有7個節(jié)點(diǎn)某残,那么鏡像數(shù)肯定是5;而我們集群只有3個節(jié)點(diǎn)陵吸,因此鏡像數(shù)量就是3.
5.2.測試
可以參考對鏡像集群的測試玻墅,效果是一樣的。
5.3.集群擴(kuò)容
5.3.1.加入集群
1)啟動一個新的MQ容器:
docker run -d --net mq-net \
-v ${PWD}/.erlang.cookie:/var/lib/rabbitmq/.erlang.cookie \
-e RABBITMQ_DEFAULT_USER=itcast \
-e RABBITMQ_DEFAULT_PASS=123321 \
--name mq4 \
--hostname mq5 \
-p 8074:15672 \
-p 8084:15672 \
rabbitmq:3.8-management
2)進(jìn)入容器控制臺:
docker exec -it mq4 bash
3)停止mq進(jìn)程
rabbitmqctl stop_app
4)重置RabbitMQ中的數(shù)據(jù):
rabbitmqctl reset
5)加入mq1:
rabbitmqctl join_cluster rabbit@mq1
6)再次啟動mq進(jìn)程
rabbitmqctl start_app
5.3.2.增加仲裁隊列副本
我們先查看下quorum.queue這個隊列目前的副本情況壮虫,進(jìn)入mq1容器:
docker exec -it mq1 bash
執(zhí)行命令:
rabbitmq-queues quorum_status "quorum.queue"
結(jié)果:
現(xiàn)在澳厢,我們讓mq4也加入進(jìn)來:
rabbitmq-queues add_member "quorum.queue" "rabbit@mq4"
結(jié)果:
再次查看:
rabbitmq-queues quorum_status "quorum.queue"
查看控制臺,發(fā)現(xiàn)quorum.queue的鏡像數(shù)量也從原來的 +2 變成了 +3: