目录
概念
任何一个服务,如果仅仅是单机部署,那么性能总是有上限的,RabbitMQ
也不例外,当单台 RabbitMQ
服务处理消息的能力到达瓶颈时,可以通过集群来实现高可用和负载均衡。
通常情况下,在集群中我们把每一个服务称之为一个节点,在 RabbitMQ
集群中,节点类型可以分为两种:
-
内存节点:元数据存放于内存中。为了重启后能同步数据,内存节点会将磁盘节点的地址存放于磁盘之中,除此之外,如果消息被持久化了也会存放于磁盘之中,因为内存节点读写速度快,一般客户端会连接内存节点。
-
磁盘节点:元数据存放于磁盘中(默认节点类型),需要保证至少一个磁盘节点,否则一旦宕机,无法恢复数据,从而也就无法达到集群的高可用目的。
PS:元数据,指的是包括队列名字属性、交换机的类型名字属性、绑定信息、vhost等基础信息,不包括队列中的消息数据。
RabbitMQ
中的集群主要有两种模式:普通集群模式和镜像队列模式。
普通集群模式
在普通集群模式下,集群中各个节点之间只会相互同步元数据,也就是说,消息数据不会被同步。那么问题就来了,假如我们连接到 A
节点,但是消息又存储在 B
节点又怎么办呢?
不论是生产者还是消费者,假如连接到的节点上没有存储队列数据,那么内部会将其转发到存储队列数据的节点上进行存储。虽然说内部可以实现转发,但是因为消息仅仅只是存储在一个节点,那么假如这节点挂了,消息是不是就没有了?这个问题确实存在,所以这种普通集群模式并没有达到高可用的目的。
IP | role |
---|---|
192.168.142.155 | node1 |
192.168.142.156 | node2 |
192.168.142.157 | node3 |
分别在三台主机上添加 hosts
127.0.0.1 localhost
127.0.1.1 node1
192.168.142.155 node1
192.168.142.156 node2
192.168.142.157 node3
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 node2
192.168.142.155 node1
192.168.142.156 node2
192.168.142.157 node3
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
127.0.0.1 localhost
127.0.1.1 node3
192.168.142.155 node1
192.168.142.156 node2
192.168.142.157 node3
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
为三台主机添加 rabbitmq 用户
# 停止服务
rabitmq-server stop
# 开启 web 管理界面插件
rabbitmq-plugins enable rabbitmq_management
# 创建用户
rabbitmqctl add_user hq 123456
# 加入 administrator 组
rabbitmqctl set_user_tags hq administrator
# 设置用户权限
# 三个 “。*” 分别代表可配置,可读,可写
rabbitmqctl set_permissions -p / hq ".*" ".*" ".*"
# 重启启动
rabbitmq-plugins enable rabbitmq_management
# 在浏览器端通过本机 ip 访问,端口是 15672
# 查看用户
rabbitmqctl list_users
root@node1:~# rabbitmqctl list_users
Listing users ...
user tags
hq [administrator]
guest [administrator]
root@node2:~# rabbitmqctl list_users
Listing users ...
user tags
guest [administrator]
hq [administrator]
root@node3:~# rabbitmqctl list_users
Listing users ...
user tags
hq [administrator]
guest [administrator]
# 用户创建好之后三台主机都可以访问 web 页了
通过 ip + 15672 端口访问 web 页
为三台主机书写 docker-compose.yml 文件,我这里的文件名为 rabbit-cluster.yml
services:
rabbitmq:
container_name: rabbitmq
image: rabbitmq:3.13.7-management
network_mode: host
volumes:
- ./data:/var/lib/rabbitmq
- /etc/localtime:/etc/localtime:ro
extra_hosts:
- node3:192.168.142.157
- node2:192.168.142.156
- node1:192.168.142.155
启动
docker compose -f rabbitmq-cluster.yml up -d
如果拉取不下来,我们可以配置加速器
书写 daemon.json 文件,没有该文件的就新建
vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://docker.m.daocloud.io"]
}
重启 docker
systemctl restart docker.service
再尝试拉取
拉起来之后,我们同步一下三台主机之间的 .erlang.cookie 文件
随机选取一台主机的文件进行同步就行
node1
abc=docker exec -it rabbitmq bash -c "cat /var/lib/rabbitmq/.erlang.cookie"
echo $abc > /data/.erlang.cookie
scp .erlang.cookie 192.168.142.156:/home/node2
scp .erlang.cookie 192.168.142.157:/home/node3
node2
mv /home/node2 /data/.erlang.cookie
chown lxd:docker /data/.erlang.cookie
chmod 400 /data/.erlang.cookie
node3
mv /home/node3 /data/.erlang.cookie
chown lxd:docker /data/.erlang.cookie
chmod 400 /data/.erlang.cookie
将 node2 node3 加入 node1 集群中,在这之前要保证 node1 是启动的状态
node1
docker exec -it rabbitmq bash -c "rabbitmqctl start_app"
node2 node3
docker exec -it rabbitmq bash -c "rabbitmqctl stop_app"
docker exec -it rabbitmq bash -c "rabbitmqctl reset"
将 node2 加入内存节点
docker exec -it rabbitmq bash -c "rabbitmqctl join_cluster --ram rabbit@node1"
将 node3 加入磁盘节点
docker exec -it rabbitmq bash -c "rabbitmqctl join_cluster --disc rabbit@node1"
随机选择一台查看状态
docker exec -it rabbitmq bash -c "rabbitmqctl cluster_status"
...
Running Nodes
rabbit@node1
rabbit@node2
rabbit@node3
Versions
rabbit@node1: RabbitMQ 3.13.7 on Erlang 26.2.5.3
rabbit@node2: RabbitMQ 3.13.7 on Erlang 26.2.5.3
rabbit@node3: RabbitMQ 3.13.7 on Erlang 26.2.5.3
CPU Cores
Node: rabbit@node1, available CPU cores: 4
Node: rabbit@node2, available CPU cores: 4
Node: rabbit@node3, available CPU cores: 4
Maintenance status
Node: rabbit@node1, status: not under maintenance
Node: rabbit@node2, status: not under maintenance
Node: rabbit@node3, status: not under maintenance
...
见此消息说明集群配置成功
注意事项:
-
cookie在所有节点上必须完全一样,同步时一定要注意。
-
erlang是通过主机名来连接服务,必须保证各个主机名之间可以ping通。可以通过编辑/etc/hosts来手工添加主机名和IP对应关系。如果主机名ping不通,rabbitmq服务启动会失败。
-
如果queue是非持久化queue,则如果创建queue的那个节点失败,发送方和接收方可以创建同样的queue继续运作。但如果是持久化queue,则只能等创建queue的那个节点恢复后才能继续服务。
-
在集群元数据有变动的时候需要有disk node在线,但是在节点加入或退出的时候所有的disk node必须全部在线。如果没有正确退出disk node,集群会认为这个节点当掉了,在这个节点恢复之前不要加入其它节点。
镜像列队模式
镜像队列模式下,节点之间不仅仅会同步元数据,消息内容也会在镜像节点间同步,可用性更高。这种方案提升了可用性的同时,因为同步数据之间也会带来网络开销从而在一定程度上会影响到性能。
镜像队列模式本质上,就是在普通集群模式的基础上配置队列的同步
在任意节点执行
rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
在所有节点上
# 将名称以ha开头的队列同步至所有节点:
rabbitmqctl set_policy ha-all "^ha.*" '{"ha-mode": "all"}'
# 将所有队列至少同步至两个节点:
rabbitmqctl set_policy ha-two "^.*" '{"ha-mode": "exactly", "ha-params": 2, "ha-sync-mode": "automatic"}'
查看镜像队列配置
# 在任意节点上查看相应的策略:
rabbitmqctl list_policies
Listing policies for vhost "/" ...
vhost name pattern apply-to definition priority
/ ha-all ^ha.* all {"ha-mode":"all"} 0
/ ha-two ^.* all {"ha-mode":"exactly","ha-params":2,"ha-sync-mode":"automatic"} 0
同时,我们也可以根据 web 页进行查看,也可以在 web 页上进行镜像队列的配置
验证
在任意节点上添加消息
此时我们换一个节点再查看
数据成功同步
删除消息步骤
换一台主机看看情况
至此,rabbitmq 集群的数据同步就已经实现了
标签:队列,rabbitmq,rabbitmqctl,ip6,Rabbitmq,镜像,node3,ha,节点 From: https://blog.csdn.net/qq_62866151/article/details/142458617