上一节,我们用docker-compose搭建了一个RabbitMQ集群,这一节我们来分析一下集群的原理
前面我们有介绍到 RabbitMQ 内部有各种基础构件,包括队列、交换器、绑定、虚拟主机等,他们组成了 AMQP 协议消息通信的基础,而这些构件以元数据的形式存在,它始终记录在 RabbitMQ 内部,它们分别是:
PS:元数据,指的是包括队列名字属性、交换机的类型名字属性、绑定信息、vhost等基础信息,不包括队列中的消息数据。
在单节点 RabbitMQ 上,仅允许该节点是磁盘节点,这样确保了节点发生故障或重启节点之后,所有关于系统的配置与元数据信息都会从磁盘上恢复。
而在 RabbitMQ 集群上,至少有一个磁盘节点,也就是在集群环境中需要添加 2 台及以上的磁盘节点,这样其中一台发生故障了,集群仍然可以保持运行。其它节点均设置为内存节点,这样会让队列和交换器声明之类的操作会更加快速,元数据同步也会更加高效。
在单个节点上,RabbitMQ 存储数据有两种方案:
如下图所示,三个节点的集群,有两个磁盘模式,一个内存模式
在集群中的每个节点,要么是内存节点,要么是磁盘节点,如果是内存节点,会将所有的元数据信息仅存储到内存中,而磁盘节点则不仅会将所有元数据存储到内存上, 还会将其持久化到磁盘。
在单节点 RabbitMQ 上,仅允许该节点是磁盘节点,这样确保了节点发生故障或重启节点之后,所有关于系统的配置与元数据信息都会从磁盘上恢复。
而在 RabbitMQ 集群上,至少有一个磁盘节点,也就是在集群环境中需要添加 2 台及以上的磁盘节点,这样其中一台发生故障了,集群仍然可以保持运行。其它节点均设置为内存节点,这样会让队列和交换器声明之类的操作会更加快速,元数据同步也会更加高效。
集群主要有两种模式主备模式(Warren)和镜像模式(Mirror)
下面分别对两种模式进行说明
1、基本特征
2、数据消费
进行数据消费时随机连接到一个节点,当队列不是当前节点创建的时候,需要有一个从创建队列的实例拉取队列数据的开销。此外由于需要固定从单实例获取数据,因此会出现单实例的瓶颈。
3、优点:
可以由多个节点消费单个队列的数据,提高了吞吐量
4、缺点:
节点实例需要拉取数据,因此集群内部存在大量的数据传输可用性保障低,一旦创建队列的节点宕机,只有等到该节点恢复其他节点才能继续消费消息
1、基本特征
创建的queue,不论是元数据还是完整数据都会在每一个节点上保存一份
向queue中写消息时,都会自动同步到每一个节点上
2、优点:
3、缺点:
下面的链接是最快最简单的一种集群部署方法
3分钟部署一个RabbitMQ集群
由于是docker部署,所以我任意找一个节点,进入集群节点
先docker ps查看运行的进程,然后根据容器id,进入容器
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4d75d7be9cf5 bitnami/rabbitmq "/opt/bitnami/script…" 7 minutes ago Up 7 minutes 4369/tcp, 5551-5552/tcp, 5671-5672/tcp, 15671-15672/tcp, 25672/tcp mycompose-queue-disc1-1
b4f7618ffdd4 bitnami/rabbitmq "/opt/bitnami/script…" 7 minutes ago Up 7 minutes 4369/tcp, 5551-5552/tcp, 5671-5672/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp mycompose-stats-1
f3a97e8d74de bitnami/rabbitmq "/opt/bitnami/script…" 7 minutes ago Up 7 minutes 4369/tcp, 5551-5552/tcp, 5671-5672/tcp, 15671-15672/tcp, 25672/tcp mycompose-queue-ram1-1
[root@localhost ~]# docker exec -it 4d /bin/bash
查看集群状态
I have no name!@4d75d7be9cf5:/$ rabbitmqctl cluster_status
Cluster status of node rabbit@queue-disc1 ...
Basics
#下面是主节点名称
Cluster name: rabbit@4d75d7be9cf5
#下面是磁盘节点,有两个
Disk Nodes
rabbit@queue-disc1
rabbit@stats
#下面是内存节点,有一个
RAM Nodes
rabbit@queue-ram1
#下面表示有三个节点在运行
Running Nodes
rabbit@queue-disc1
rabbit@queue-ram1
rabbit@stats
# 下面是版本号
Versions
rabbit@queue-disc1: RabbitMQ 3.9.11 on Erlang 24.2
rabbit@queue-ram1: RabbitMQ 3.9.11 on Erlang 24.2
rabbit@stats: RabbitMQ 3.9.11 on Erlang 24.2
Maintenance status
Node: rabbit@queue-disc1, status: not under maintenance
Node: rabbit@queue-ram1, status: not under maintenance
Node: rabbit@stats, status: not under maintenance
Alarms
(none)
Network Partitions
(none)
Listeners
Node: rabbit@queue-disc1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@queue-disc1, interface: [::], port: 15692, protocol: http/prometheus, purpose: Prometheus exporter API over HTTP
Node: rabbit@queue-disc1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@queue-ram1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@queue-ram1, interface: [::], port: 15692, protocol: http/prometheus, purpose: Prometheus exporter API over HTTP
Node: rabbit@queue-ram1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@stats, interface: [::], port: 15672, protocol: http, purpose: HTTP API
Node: rabbit@stats, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@stats, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Feature flags
Flag: drop_unroutable_metric, state: enabled
Flag: empty_basic_get_metric, state: enabled
Flag: implicit_default_bindings, state: enabled
Flag: maintenance_mode_status, state: enabled
Flag: quorum_queue, state: enabled
Flag: stream_queue, state: enabled
Flag: user_limits, state: enabled
Flag: virtual_host_metadata, state: enabled
从上面可以看到,有三个节点,其中有两个磁盘节点,一个内存节点
上面有三个节点:rabbit@queue-disc1,rabbit@queue-ram1,rabbit@stats。我们剔除rabbit@queue-disc1
进入rabbit@queue-disc1所在的容器,并执行rabbitmqctl stop_app
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b31e921dd5e7 bitnami/rabbitmq "/opt/bitnami/script…" 4 hours ago Up 2 hours 4369/tcp, 5551-5552/tcp, 5671/tcp, 15671-15672/tcp, 25672/tcp, 0.0.0.0:5612->5672/tcp, :::5612->5672/tcp mycompose-queue-disc1-1
ed73deb9f1c5 bitnami/rabbitmq "/opt/bitnami/script…" 4 hours ago Up 2 hours 4369/tcp, 5551-5552/tcp, 5671/tcp, 15671/tcp, 25672/tcp, 0.0.0.0:15672->15672/tcp, :::15672->15672/tcp, 0.0.0.0:5602->5672/tcp, :::5602->5672/tcp mycompose-stats-1
[root@localhost ~]# docker exec -it b3 /bin/bash
I have no name!@b31e921dd5e7:/$ rabbitmqctl stop_app
Stopping rabbit application on node rabbit@queue-disc1 ...
进入rabbit@stats节点,然后执行下面的命令
I have no name!@ed73deb9f1c5:/$ rabbitmqctl forget_cluster_node rabbit@queue-disc1
Removing node rabbit@queue-disc1 from the cluster
可以看到,现在只有两个节点了,其中有一个内存节点,由于某些原因,没有启动起来。先暂时不用管。
刚才的rabbit@queue-disc1被我们剔除了集群,现在我们又尝试把该节点重新加入集群
rabbitmqctl join_cluster rabbit@stats 加入刚才的集群,并重启一下
I have no name!@b31e921dd5e7:/$ rabbitmqctl join_cluster rabbit@stats
Clustering node rabbit@queue-disc1 with rabbit@stats
I have no name!@b31e921dd5e7:~$ rabbitmqctl start_app
Starting node rabbit@queue-disc1 ...
rabbit@queue-disc1又回来了
将rabbit@queue-disc1节点改变成内存节点,如下所示,先停止应用,再用change_cluster_node_type命令改变为ram类型,最后重启
I have no name!@b31e921dd5e7:~$ rabbitmqctl stop_app
Stopping rabbit application on node rabbit@queue-disc1 ...
I have no name!@b31e921dd5e7:~$ rabbitmqctl change_cluster_node_type ram
Turning rabbit@queue-disc1 into a ram node
I have no name!@b31e921dd5e7:~$ rabbitmqctl start_app
可以看到节点类型已变成ram了