在RabbitMQ
的官方文档中,讲述了两种集群的配置方式:
MQ
都有自己的队列、数据信息(其它元数据信息如交换机等会同步)。例如我们有2个MQ
:mq1
,和mq2
,如果你的消息在mq1
,而你连接到了mq2
,那么mq2
会去mq1
拉取消息,然后返回给你。如果mq1
宕机,消息就会丢失。mq
的镜像节点之间同步,因此你连接到任何一个镜像节点,均可获取到消息。而且如果一个节点宕机,并不会导致数据丢失。不过,这种方式增加了数据同步的带宽消耗。我们先来看普通模式集群,我们的计划部署3节点的mq
集群:
主机名 | 控制台端口 | amqp 通信端口 |
---|---|---|
mq1 |
15672--->15672 |
25672---> 5672 |
mq2 |
15673---> 15672 |
25673---> 5672 |
mq3 |
15674---> 15672 |
25674 ---> 5672 |
集群中的节点标示默认都是:rabbit@[hostname]
,因此以上三个节点的名称分别为:
rabbit@mq1
rabbit@mq2
rabbit@mq3
cookie
RabbitMQ
底层依赖于Erlang
,而Erlang
虚拟机就是一个面向分布式的语言,默认就支持集群模式。集群模式中的每个RabbitMQ
节点使用cookie
来确定它们是否被允许相互通信。
要使两个节点能够通信,它们必须具有相同的共享秘密,称为Erlang cookie
。cookie
只是一串最多 255 个字符的字母数字字符。
每个集群节点必须具有相同的cookie
。实例之间也需要它来相互通信。
我们先在之前启动的mq
容器中获取一个cookie
值,作为集群的cookie
。执行下面的命令:
docker exec -it mq cat /var/lib/rabbitmq/.erlang.cookie
可以看到cookie
值如下:
TUCJVNAONNFSSVRDJGSW
接下来,停止并删除当前的mq
容器,我们重新搭建集群。
docker rm -f mq
在/home/rabbitmq
目录新建一个配置文件rabbitmq.conf
:
cd /home/rabbitmq
# 创建文件
touch rabbitmq.conf
文件内容如下:
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
再创建一个文件,记录cookie
cd /home/rabbitmq
# 创建cookie文件
touch .erlang.cookie
# 写入cookie
echo "TUCJVNAONNFSSVRDJGSW" > .erlang.cookie
# 修改cookie文件的权限
chmod 600 .erlang.cookie
准备三个目录mq1
、mq2
、mq3
:
cd /home/rabbitmq
# 创建目录
mkdir mq1 mq2 mq3
然后拷贝rabbitmq.conf
、cookie
文件到mq1
、mq2
、mq3
:
# 进入/home/rabbitmq
cd /home/rabbitmq
# 拷贝
cp rabbitmq.conf mq1
cp rabbitmq.conf mq2
cp rabbitmq.conf mq3
cp .erlang.cookie mq1
cp .erlang.cookie mq2
cp .erlang.cookie mq3
创建一个网络:
docker network create mq-net
运行命令
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=dcxuexi \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq1 \
--hostname mq1 \
-p 25672:5672 \
-p 15672:15672 \
rabbitmq:3.11-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=dcxuexi \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq2 \
--hostname mq2 \
-p 25673:5672 \
-p 15673:15672 \
rabbitmq:3.11-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=dcxuexi \
-e RABBITMQ_DEFAULT_PASS=123456 \
--name mq3 \
--hostname mq3 \
-p 25674:5672 \
-p 15674:15672 \
rabbitmq:3.11-management
在mq1
这个节点上添加一个队列:
如图,在mq2
和mq3
两个控制台也都能看到:
点击这个队列,进入管理页面:
然后利用控制台发送一条消息到这个队列:
结果在mq2
、mq3
上都能看到这条消息:
我们让其中一台节点mq1
宕机:
docker stop mq1
然后登录mq2
或mq3
的控制台,发现simple.queue
也不可用了:
说明数据并没有拷贝到mq2
和mq3
。