1 前言

RabbitMQ集群分为两种模式:

  • 普通模式:创建好RabbitMQ之后的默认模式。
  • 镜像模式:把需要的队列做成镜像队列。

普通集群模式

queue 创建之后,如果没有其它 policy,消息实体只存在于其中一个节点, A、 B 两个 Rabbitmq 节点仅有相同的元数据,即队列结构,但队列的数据仅保存有一份,即创建该队列的 rabbitmq 节点(A 节点),当消息进入 A 节点的 Queue 中后, consumer 从 B 节点拉取时, RabbitMQ 会临时在 A、 B 间进行消息传输,把 A 中的消息实体取出并经过 B 发送给 consumer,所以 consumer 可以连接每一个节点,从中取消息,该模式存在一个问题就是当 A 节点故障后,B节点无法取到 A 节点中还未消费的消息实体。

镜像集群模式

把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的HA方案(镜像模式是在普通模式的基础上,增加一些镜像策略)该模式解决了上述问题,其实质和普通模式不同之处在于,消息实体会主动在镜像节点间同步,而不是在consumer取数据时临时拉取。该模式带来的副作用也很明显,除了降低系统性能外,如果镜像队列数量过多,加之大量的消息进入,集群内部的网络带宽将会被这种同步通讯大大消耗掉。所以在对可靠性要求较高的场合中适用,一个队列想做成镜像队列,需要先设置 policy,然后客户端创建队列的时候, rabbitmq 集群根据“队列名称”自动设置是普通集群模式或镜像队列。

RabbitMQ集群中有两种节点类型

  • 内存节点:只将数据保存到内存。
  • 磁盘节点:保存数据到内存和磁盘。
    内存节点虽然不写入磁盘,但是它执行效率比磁盘节点要好,集群中,只需要一个磁盘节点来保存数据就足够了,如果集群中只有内存节点,那么,不能全部停止它们,否则所有数据消息在服务器全部停机之后都会丢失。

推荐使用方案

在一个 rabbitmq 集群里,有 3 台或以上机器,其中 1 台使用磁盘模式,其它节点使用内存模式,内存节点访问速度更快,由于磁盘 IO 相对较慢,因此可作为数据备份使用。

2 环境

IP 主机名 角色 rabbitmq版本 erlang版本
192.168.7.11 rabbitmq-server1 内存节点 3.8.3 22.3.4
192.168.7.12 rabbitmq-server2 内存节点 3.8.3 22.3.4
192.168.7.13 rabbitmq-server3 磁盘节点 3.8.3 22.3.4

OS:CentOS7.4
firewalld和SELinux:禁用
erlang下载地址
rabbitmq下载地址
同步系统时间

3 安装部署

3.1 主机名解析设置

集群中的每台服务器都要同步

# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.7.11 rabbitmq-server1
192.168.7.12 rabbitmq-server2
192.168.7.13 rabbitmq-server3

3.2 各服务器安装RabbitMQ

这里分别演示通过下载指定版本的rpm包安装和通过编写.repo文件安装的两种方式

3.2.1 下载指定版本的rpm包安装

在安装rabbitmq之前,必须安装受支持的erlang版本,rabbitmq和erlang的版本兼容性要求参考这里

安装erlang
# wget https://dl.bintray.com/rabbitmq-erlang/rpm/erlang/22/el/7/x86_64/erlang-22.3.4-1.el7.x86_64.rpm
# yum -y install erlang-22.3.4-1.el7.x86_64.rpm

安装rabbitmq
# wget https://dl.bintray.com/rabbitmq/rpm/rabbitmq-server/v3.8.x/el/7/noarch/rabbitmq-server-3.8.3-1.el7.noarch.rpm
# yum -y install rabbitmq-server-3.8.3-1.el7.noarch.rpm

3.2.2 编写.repo文件安装

# cat rabbitmq.repo 
[bintray-rabbitmq-server]
name=bintray-rabbitmq-rpm
baseurl=https://dl.bintray.com/rabbitmq/rpm/rabbitmq-server/v3.8.x/el/7
gpgcheck=1
gpgkey=https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
enabled=1

[bintray-rabbitmq-erlang]
name=bintray-erlang-rpm
baseurl=https://dl.bintray.com/rabbitmq-erlang/rpm/erlang/22/el/7
gpgcheck=1
gpgkey=https://dl.bintray.com/rabbitmq/Keys/rabbitmq-release-signing-key.asc
enabled=1

# yum -y install erlang rabbitmq-server

3.3 启动RabbitMQ服务并设置为开机启动

# systemctl enable --now rabbitmq-server

3.4 创建RabbitMQ集群

Rabbitmq 的集群是依赖于 erlang 的集群来工作的,所以必须先构建起 erlang 的集群环境,而 Erlang 的集群中各节点是通过一个 magic cookie 来实现的,这个cookie 存放在 /var/lib/rabbitmq/.erlang.cookie 中,文件是 400 的权限,所以必须保证各节点 cookie 保持一致,否则节点之间就无法通信。

3.4.1 各服务器同步cookie文件

各服务器先关闭rabbitmq服务
# systemctl stop rabbitmq-server
在rabbitmq-server1向其它两个服务器同步cookie文件
# for i in 12 13 ; do scp /var/lib/rabbitmq/.erlang.cookie 192.168.7.$i:/var/lib/rabbitmq/ ; done
各服务器启动rabbitmq服务
# systemctl start rabbitmq-server

3.4.2 查看当前集群状态

[root@rabbitmq-server1 ~]# rabbitmqctl cluster_status 
Cluster status of node rabbit@rabbitmq-server1 ...
Basics

Cluster name: rabbit@rabbitmq-server1

Disk Nodes

rabbit@rabbitmq-server1

Running Nodes

rabbit@rabbitmq-server1

Versions

rabbit@rabbitmq-server1: RabbitMQ 3.8.3 on Erlang 22.3.4

Alarms

(none)

Network Partitions

(none)

Listeners

Node: rabbit@rabbitmq-server1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0

Feature flags

Flag: implicit_default_bindings, state: enabled
Flag: quorum_queue, state: enabled
Flag: virtual_host_metadata, state: enabled

[root@rabbitmq-server2 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq-server2 ...
Basics

Cluster name: rabbit@rabbitmq-server2

Disk Nodes

rabbit@rabbitmq-server2

Running Nodes

rabbit@rabbitmq-server2

Versions

rabbit@rabbitmq-server2: RabbitMQ 3.8.3 on Erlang 22.3.4

Alarms

(none)

Network Partitions

(none)

Listeners

Node: rabbit@rabbitmq-server2, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server2, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0

Feature flags

Flag: implicit_default_bindings, state: enabled
Flag: quorum_queue, state: enabled
Flag: virtual_host_metadata, state: enabled

[root@rabbitmq-server3 ~]# rabbitmqctl cluster_status
Cluster status of node rabbit@rabbitmq-server3 ...
Basics

Cluster name: rabbit@rabbitmq-server3

Disk Nodes

rabbit@rabbitmq-server3

Running Nodes

rabbit@rabbitmq-server3

Versions

rabbit@rabbitmq-server3: RabbitMQ 3.8.3 on Erlang 22.3.4

Alarms

(none)

Network Partitions

(none)

Listeners

Node: rabbit@rabbitmq-server3, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server3, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0

Feature flags

Flag: implicit_default_bindings, state: enabled
Flag: quorum_queue, state: enabled
Flag: virtual_host_metadata, state: enabled

3.4.3 创建RabbitMQ集群

3.4.3.1 在rabbitmq-server1作为内存节点连接起来,并作为内存节点,在rabbitmq-server1上执行以下命令

停止app服务
# rabbitmqctl stop_app 
Stopping rabbit application on node rabbit@rabbitmq-server1 ...

清空元数据
# rabbitmqctl reset 
Resetting node rabbit@rabbitmq-server1 ...

将 rabbitmq-server1 添加到集群当中,并成为内存节点,不加--ram 默认是磁盘节点
# rabbitmqctl join_cluster rabbit@rabbitmq-server3 --ram
Clustering node rabbit@rabbitmq-server1 with rabbit@rabbitmq-server3

启动app服务
# rabbitmqctl start_app 
Starting node rabbit@rabbitmq-server1 ...
 completed with 0 plugins.

3.4.3.2 在rabbitmq-server2作为内存节点连接起来,并作为内存节点,在rabbitmq-server2上执行以下命令

操作步骤同上

3.4.4 将集群设置为镜像模式

以下操作只需要在集群中的其中一台节点执行

# rabbitmqctl set_policy ha-all "#" '{"ha-mode":"all"}'
Setting policy "ha-all" for pattern "#" to "{"ha-mode":"all"}" with priority "0" for vhost "/" ...

3.4.5 验证当前集群状态

[root@rabbitmq-server1 ~]# rabbitmqctl cluster_status 
Cluster status of node rabbit@rabbitmq-server1 ...
Basics

Cluster name: rabbit@rabbitmq-server3

Disk Nodes

rabbit@rabbitmq-server3

RAM Nodes

rabbit@rabbitmq-server1
rabbit@rabbitmq-server2

Running Nodes

rabbit@rabbitmq-server1
rabbit@rabbitmq-server2
rabbit@rabbitmq-server3

Versions

rabbit@rabbitmq-server1: RabbitMQ 3.8.3 on Erlang 22.3.4
rabbit@rabbitmq-server2: RabbitMQ 3.8.3 on Erlang 22.3.4
rabbit@rabbitmq-server3: RabbitMQ 3.8.3 on Erlang 22.3.4

Alarms

(none)

Network Partitions

(none)

Listeners

Node: rabbit@rabbitmq-server1, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server1, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@rabbitmq-server2, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server2, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@rabbitmq-server3, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@rabbitmq-server3, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0

Feature flags

Flag: implicit_default_bindings, state: enabled
Flag: quorum_queue, state: enabled
Flag: virtual_host_metadata, state: enabled

4 web界面验证当前集群状态

4.1 各服务器启动web插件

# rabbitmq-plugins enable rabbitmq_management
启动web插件后会监听15672端口,该端口是web管理端口
# ss -nlt|grep 15672
LISTEN     0      128          *:15672                    *:*

4.2 登录web管理界面

rabbitmq 从 3.3.0 开始禁止使用 guest/guest 权限通过除 localhost 外的访问,直
接访问报错如下:
rpm包方式安装RabbitMQ集群
允许方式,每个节点都操作

# vim /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.3/ebin/rabbit.app
39 {loopback_users, []}, #删除被禁止登陆的 guest 账户
# systemctl restart rabbitmq-server.service #重启 rabbitmq 服务

4.3 开启web插件后的集群状态

rpm包方式安装RabbitMQ集群

5 RabbitMQ常用命令

# 创建vhost
[root@rabbitmq-server1 ~]# rabbitmqctl add_vhost hechunping
Adding vhost "hechunping" ...

# 列出所有vhost
[root@rabbitmq-server1 ~]# rabbitmqctl list_vhosts
Listing vhosts ...
name
/
hechunping

# 列出所有队列
[root@rabbitmq-server1 ~]# rabbitmqctl list_queues 
Timeout: 60.0 seconds ...
Listing queues for vhost / ...

# 删除指定vhost
[root@rabbitmq-server1 ~]# rabbitmqctl delete_vhost hechunping
Deleting vhost "hechunping" ...

# 添加账户hechunping密码为123.com
[root@rabbitmq-server1 ~]# rabbitmqctl add_user hechunping 123.com
Adding user "hechunping" ...

# 更改用户hechunping密码
[root@rabbitmq-server1 ~]# rabbitmqctl change_password hechunping 123456
Changing password for user "hechunping" ...

# 设置 hechunping 用户对 hechunping 的 vhost 有读写权限,三个点分别表示配置正则、读和写
[root@rabbitmq-server1 ~]# rabbitmqctl set_permissions -p hechunping hechunping ".*" ".*" ".*"
Setting permissions for user "hechunping" in vhost "hechunping" ...

rpm包方式安装RabbitMQ集群