一、前言
1.1. 安装注意点
本手册发布时,官方已经发布了 3.12.4、3.11.22、3.10.25 三个分支的最新版,读者根据自己的情况选择版本。
通过查阅官方文档,本手册中涉及的概念信息未发生变化,仍然适用。
本手册编写时,rabbitmq-server 时官方已经发布了 3.11.1 版本,通过官方指定的第三方仓库安装 3.11.1 成功并成功启动服务,但是无法正常访问插件方式安装的管理界面,管理界面端口监听正常但是通过浏览器访问时提示503错误,多次尝试后,手动安装 erlang 25.1.1,rabbitmq-server 3.10.9 版本,正常完成。
踩坑点:
-
官方 yum 方式安装 3.11.1 版本无法正常启用管理页面
-
官方提供的 yum 第三方库方式无法安装 3.10.9
-
官方提供的 packagecloud.io yum 第三方库没有适配最新的 erlang 版本
-
通过 yum 命令卸载 rabbitmq-server 之后,并不会清楚残留 rabbitmq-server 配置信息和数据,需要手动删除三个目录
/var/lib/rabbitmq
、/var/run/rabbitmq
、/etc/rabbitmq
,否则发生版本冲突导致启动失败,提示以下信息:
2022-10-18 11:40:29.056115+08:00 [warning] <0.222.0> Feature flags: the previous instance of this node must have failed to write the
feature_flags
file at/var/lib/rabbitmq/mnesia/rabbit@localhost-feature_flags
:…
2022-10-18 11:40:30.062485+08:00 [notice] <0.44.0> Application rabbit exited with reason: { {schema_integrity_check_failed,[{table_missing,rabbit_listener}]},{rabbit,start,[normal,[]]}}
1.2. 概念
1)集群中的节点复制了什么?
运行RabbitMQ brokers 所需的所有数据/状态会在所有节点上复制,但不包括消息队列,默认情况下,消息队列驻留在一个节点上,尽管它们可以在所有节点的管理页面可见和访问。要跨集群中的节点复制队列,请使用支持复制的队列类型,例如 streams,、quorum queues、classic mirrored queues。
2)集群所有节点都平等的(peers)
一些分布式系统有领导者和追随者节点。RabbitMQ 通常不是这样。RabbitMQ集群中的所有节点都是相等的对等节点:RabbitMQ核心中没有特殊节点。当考虑到Quorum Queues](https://www.rabbitmq.com/migrate-mcq-to-qq.html)方案时,节点的个数会要求奇数个,因为需要大多数节点投票决定队列的leader,但就大多数意图和目的而言,所有集群节点都应被视为平等。
许多CLI工具操作可以针对任何节点执行。HTTP API客户端可以针对任何集群节点。
单个插件可以在一段时间内指定(选择)某些节点为“特殊”。例如,联合链接位于特定的集群节点上。如果该节点失败,链接将在另一个节点上重新启动。
在旧的(长期维护的)版本中,RabbitMQ管理插件使用专用节点进行统计收集和聚合。
3)集群和客户端
假设所有集群成员都可用,客户端可以连接到任何节点并执行任何操作。节点将以透明的方式将操作路由到 quorum queues
领导者或队列领导者副本。
对于所有受支持的消息协议,客户端一次只连接到一个节点。
在节点故障的情况下,客户端应该能够重新连接到另一个节点,恢复其拓扑并继续操作。因此,大多数客户端库接受连接点列表(主机名或IP地址)作为连接选项。如果客户端支持,主机列表将在初始连接和连接恢复期间使用。请参阅文档指南以了解更多信息。
使用 quorum queues
和 streams
,客户端只能对具有在线副本法定人数的队列执行操作。
使用 classic mirrored queues
时,如果故障节点上有非镜像队列,客户端在连接到另一个节点后可能无法顺畅的接续业务操作(个人理解:部分数据留在了故障节点,无法正常访问到)。
4)节点故障处理
RabbitMQ brokers 可以容忍单个节点的故障。节点可以随意启动和停止,只要它们可以联系关机时已知的集群成员节点。
quorum queues
允许在多个集群节点之间并行复制队列内容。大多数副本在线时,其具有可预测的领导者选举和数据安全行为。
classic mirrored queues
非复制的经典队列也可以在集群中使用。节点故障情况下的非镜像队列行为取决于队列的持久性。
RabbitMQ集群有几种处理网络分区的模式,主要是面向一致性的。集群设计的目的是在局域网内使用,不建议运行跨广域网的集群。 Shovel 或 Federation 插件是跨广域网连接 brokers 的更好解决方案。请注意,Shovel 和 Federation 并不等同于集群。
5)指标和统计
每个节点存储和聚合自己的指标和统计信息,并为其他节点提供访问它的API。一些统计数据是集群范围的,另一些是特定于单个节点的。访问管理页面时,管理页面插件会通过 HTTP API 请求集群内节点数据,然后生成聚合结果。
在长期未维护的旧版本中,RabbitMQ 管理页面插件使用专用节点进行统计收集和聚合。
6)集群节点的启停
‼️重要:集群节点最后一个停止的节点应该是整个集群停机重启时的第一个节点。
当节点在关机期间没有 *peers(伙伴节点)*在线时,它将在没有尝试与任何已知 peers 同步的情况下启动。当它启动后,其他 peers 将能够重新加入它。
因此,当整个集群被关闭时,最后一个关闭的节点是唯一一个在关闭时没有任何运行 peers 的节点。该节点无需先联系任何其他 peers 即可启动。由于节点将尝试联系已知 peers 长达5分钟(默认情况下),因此可以在该时间内按任何顺序重新启动节点。在这种情况下,他们将一个接一个地重新加入。此时间窗口可以使用两个配置设置进行调整:
# wait for 60 seconds instead of 30
mnesia_table_loading_retry_timeout = 60000
# retry 15 times instead of 10
mnesia_table_loading_retry_limit = 15
通过调整这些设置并调整已知对等体必须返回的时间窗口,可以考虑集群范围的重新部署场景,这些场景可能超过5分钟才能完成。
在升级期间,有时最后一个要停止的节点必须是升级后启动的第一个节点。该节点将被指定为执行集群范围的模式迁移,其他节点可以从中同步并在重新加入时应用。
7)在 peers 不可用时强制启动节点
在某些情况下,最后一个离线节点无法恢复。可以使用 rabbitmqctl forget_cluster_node
命令将其从集群中删除。
或者,可以在节点上使用 rabbitmqctl force_boot
命令使其启动,而无需尝试与任何 peers 同步(就好像这个节点才是最后关闭的节点)。这通常只有在最后一个关闭的节点或一组节点永远不会重新上线时才需要这样操作。
8)集群节点类型,磁盘和RAM
节点可以是磁盘节点或RAM节点。(注:disk
和 disc
可以互换使用)。RAM节点仅将内部数据库表存储在RAM中。这不包括消息、消息存储索引、队列索引和其他节点状态。
在绝大多数情况下,所有节点都应该是磁盘节点;RAM节点是一种特殊情况,可用于提高 queues、exchanges 和 vhosts 的状态数据存储、查看性能。RAM节点不提供更高的消息速率。如有疑问,请仅使用磁盘节点。
由于RAM节点仅将内部数据库表存储在RAM中,因此它们必须在启动时从 peers 节点同步内部数据库表信息。这意味着集群必须至少包含一个磁盘节点。因此,无法手动删除集群中最后一个剩余的磁盘节点。
二、系统配置
- 为了后续的集群配置,必须给每台主机配置不一样的主机名
$ hostnamectl set-hostname node21
```
2. 然后配置每一台主机的 `/etc/hosts` 文件,以192.168.7.218为例
```shell
$ vim /etc/hosts
127.0.0.1 node218
192.168.7.218 node218
192.168.7.219 node219
三、安装
- 访问 github 下载 erlang 和 rabbitmq-server 3.10.9
$ wget https://github.com/rabbitmq/erlang-rpm/releases/download/v25.1.1/erlang-25.1.1-1.el8.x86_64.rpm
$ wget https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.10.9/rabbitmq-server-3.10.9-1.el8.noarch.rpm
- 本地安装 erlang 25.1.1 和 rabbitmq-server 3.10.9,rabbitmq 和 erlang 的版本对应关系请参照 RabbitMQ Erlang Version Requirements
$ rpm -ivh erlang-25.1.1-1.el8.x86_64.rpm rabbitmq-server-3.10.9-1.el8.noarch.rpm
Verifying... ################################# [100%]
Preparing... ################################# [100%]
Updating / installing...
1:erlang-25.1.1-1.el8 ################################# [ 50%]
2:rabbitmq-server-3.10.9-1.el8 ################################# [100%]
[/usr/lib/tmpfiles.d/rabbitmq-server.conf:1] Line references path below legacy directory /var/run/, updating /var/run/rabbitmq → /run/rabbitmq; please update the tmpfiles.d/ drop-in file accordingly.
- 确认安装的版本信息
$ rpm -qi rabbitmq-server
Name : rabbitmq-server
Version : 3.10.9
Release : 1.el8
Architecture: noarch
Install Date: Tue 18 Oct 2022 11:44:32 AM CST
Group : Development/Libraries
Size : 22048350
License : MPLv2.0 and MIT and ASL 2.0 and BSD
Signature : RSA/SHA512, Thu 13 Oct 2022 05:50:12 AM CST, Key ID 6b73a36e6026dfca
Source RPM : rabbitmq-server-3.10.9-1.el8.src.rpm
Build Date : Thu 13 Oct 2022 05:45:28 AM CST
Build Host : 0f234bfe-9cd8-435d-72a4-4d35735c3feb
Relocations : (not relocatable)
URL : https://www.rabbitmq.com/
Summary : The RabbitMQ server
Description :
RabbitMQ is an open source multi-protocol messaging broker.
- 立即启动 rabbitmq-server,并设置为开机自动启动
$ systemctl enable --now rabbitmq-server.service
Created symlink /etc/systemd/system/multi-user.target.wants/rabbitmq-server.service → /usr/lib/systemd/system/rabbitmq-server.service.
- 确认 rabbitmq-server状态
$ systemctl status rabbitmq-server.service
● rabbitmq-server.service - RabbitMQ broker
Loaded: loaded (/usr/lib/systemd/system/rabbitmq-server.service; enabled; vendor preset: disabled)
Active: active (running) since Tue 2022-10-18 11:44:42 CST; 5s ago
Main PID: 5640 (beam.smp)
Tasks: 29 (limit: 100911)
Memory: 94.9M
CGroup: /system.slice/rabbitmq-server.service
├─5640 /usr/lib64/erlang/erts-13.1.1/bin/beam.smp -W w -MBas ageffcbf -MHas ageffcbf -MBlmbcs 512 -MHlmbcs 512 -MMmcs 30 -P 1048576 -t 5000000 -stbt db -zdbbl 128000 -sbwt none -sbwtdcpu none -sbwtdio none -- -root>
├─5654 erl_child_setup 32768
├─5683 /usr/lib64/erlang/erts-13.1.1/bin/epmd -daemon
├─5708 /usr/lib64/erlang/erts-13.1.1/bin/inet_gethost 4
├─5709 /usr/lib64/erlang/erts-13.1.1/bin/inet_gethost 4
└─5712 /bin/sh -s rabbit_disk_monitor
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Doc guides: https://rabbitmq.com/documentation.html
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Support: https://rabbitmq.com/contact.html
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Tutorials: https://rabbitmq.com/getstarted.html
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Monitoring: https://rabbitmq.com/monitoring.html
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Logs: /var/log/rabbitmq/[email protected]
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: /var/log/rabbitmq/rabbit@localhost_upgrade.log
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: <stdout>
Oct 18 11:44:40 localhost.localdomain rabbitmq-server[5640]: Config file(s): (none)
Oct 18 11:44:42 localhost.localdomain rabbitmq-server[5640]: Starting broker... completed with 0 plugins.
Oct 18 11:44:42 localhost.localdomain systemd[1]: Started RabbitMQ broker.
- rabbitmq-server 内部详细信息
$ rabbitmqctl status
Status of node rabbit@localhost ...
Runtime
OS PID: 5640
OS: Linux
Uptime (seconds): 18
Is under maintenance?: false
RabbitMQ version: 3.10.9
RabbitMQ release series support status: supported
Node name: rabbit@localhost
Erlang configuration: Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Crypto library: OpenSSL 1.1.1k FIPS 25 Mar 2021
Erlang processes: 272 used, 1048576 limit
Scheduler run queue: 1
Cluster heartbeat timeout (net_ticktime): 60
Plugins
Enabled plugin file: /etc/rabbitmq/enabled_plugins
Enabled plugins:
Data directory
Node data directory: /var/lib/rabbitmq/mnesia/rabbit@localhost
Raft data directory: /var/lib/rabbitmq/mnesia/rabbit@localhost/quorum/rabbit@localhost
Config files
Log file(s)
* /var/log/rabbitmq/[email protected]
* /var/log/rabbitmq/rabbit@localhost_upgrade.log
* <stdout>
Alarms
(none)
Memory
Total memory used: 0.1281 gb
Calculation strategy: rss
Memory high watermark setting: 0.4 of available memory, computed to: 6.6382 gb
reserved_unallocated: 0.0756 gb (58.96 %)
code: 0.0315 gb (24.56 %)
other_proc: 0.0181 gb (14.16 %)
other_system: 0.014 gb (10.9 %)
other_ets: 0.0025 gb (1.98 %)
atom: 0.0013 gb (1.04 %)
metrics: 0.0007 gb (0.56 %)
binary: 0.0002 gb (0.14 %)
mnesia: 0.0001 gb (0.07 %)
plugins: 0.0 gb (0.03 %)
msg_index: 0.0 gb (0.02 %)
quorum_ets: 0.0 gb (0.02 %)
quorum_queue_dlx_procs: 0.0 gb (0.0 %)
stream_queue_procs: 0.0 gb (0.0 %)
stream_queue_replica_reader_procs: 0.0 gb (0.0 %)
allocated_unused: 0.0 gb (0.0 %)
connection_channels: 0.0 gb (0.0 %)
connection_other: 0.0 gb (0.0 %)
connection_readers: 0.0 gb (0.0 %)
connection_writers: 0.0 gb (0.0 %)
mgmt_db: 0.0 gb (0.0 %)
queue_procs: 0.0 gb (0.0 %)
queue_slave_procs: 0.0 gb (0.0 %)
quorum_queue_procs: 0.0 gb (0.0 %)
stream_queue_coordinator_procs: 0.0 gb (0.0 %)
File Descriptors
Total: 2, limit: 32671
Sockets: 0, limit: 29401
Free Disk Space
Low free disk space watermark: 0.05 gb
Free disk space: 68.471 gb
Totals
Connection count: 0
Queue count: 0
Virtual host count: 1
Listeners
Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
- 添加管理界面
$ rabbitmq-plugins enable rabbitmq_management
Enabling plugins on node rabbit@localhost:
rabbitmq_management
The following plugins have been configured:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
Applying plugin configuration to rabbit@localhost...
The following plugins have been enabled:
rabbitmq_management
rabbitmq_management_agent
rabbitmq_web_dispatch
started 3 plugins.
- 再次查看 rabbitmq-server 状态信息,能够看到管理页面相关插件以及管理页面端口
15672
已经监听
$ rabbitmqctl status
Status of node rabbit@localhost ...
Runtime
OS PID: 5640
OS: Linux
Uptime (seconds): 33
Is under maintenance?: false
RabbitMQ version: 3.10.9
RabbitMQ release series support status: supported
Node name: rabbit@localhost
Erlang configuration: Erlang/OTP 25 [erts-13.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit:ns]
Crypto library: OpenSSL 1.1.1k FIPS 25 Mar 2021
Erlang processes: 360 used, 1048576 limit
Scheduler run queue: 1
Cluster heartbeat timeout (net_ticktime): 60
Plugins
Enabled plugin file: /etc/rabbitmq/enabled_plugins
Enabled plugins:
* rabbitmq_management
* amqp_client
* rabbitmq_web_dispatch
* cowboy
* cowlib
* rabbitmq_management_agent
Data directory
Node data directory: /var/lib/rabbitmq/mnesia/rabbit@localhost
Raft data directory: /var/lib/rabbitmq/mnesia/rabbit@localhost/quorum/rabbit@localhost
Config files
Log file(s)
* /var/log/rabbitmq/[email protected]
* /var/log/rabbitmq/rabbit@localhost_upgrade.log
* <stdout>
Alarms
(none)
Memory
Total memory used: 0.1427 gb
Calculation strategy: rss
Memory high watermark setting: 0.4 of available memory, computed to: 6.6382 gb
reserved_unallocated: 0.0897 gb (62.85 %)
code: 0.0349 gb (24.44 %)
other_proc: 0.0182 gb (12.73 %)
other_system: 0.0148 gb (10.34 %)
other_ets: 0.0029 gb (2.05 %)
atom: 0.0014 gb (1.0 %)
metrics: 0.0007 gb (0.51 %)
plugins: 0.0007 gb (0.46 %)
mgmt_db: 0.0002 gb (0.13 %)
binary: 0.0002 gb (0.11 %)
mnesia: 0.0001 gb (0.06 %)
msg_index: 0.0 gb (0.02 %)
quorum_ets: 0.0 gb (0.02 %)
connection_other: 0.0 gb (0.0 %)
quorum_queue_dlx_procs: 0.0 gb (0.0 %)
stream_queue_procs: 0.0 gb (0.0 %)
stream_queue_replica_reader_procs: 0.0 gb (0.0 %)
allocated_unused: 0.0 gb (0.0 %)
connection_channels: 0.0 gb (0.0 %)
connection_readers: 0.0 gb (0.0 %)
connection_writers: 0.0 gb (0.0 %)
queue_procs: 0.0 gb (0.0 %)
queue_slave_procs: 0.0 gb (0.0 %)
quorum_queue_procs: 0.0 gb (0.0 %)
stream_queue_coordinator_procs: 0.0 gb (0.0 %)
File Descriptors
Total: 2, limit: 32671
Sockets: 0, limit: 29401
Free Disk Space
Low free disk space watermark: 0.05 gb
Free disk space: 68.5241 gb
Totals
Connection count: 0
Queue count: 0
Virtual host count: 1
Listeners
Interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Interface: [::], port: 15672, protocol: http, purpose: HTTP API
- 添加账户并授权访问管理页面,允许读写默认 vhost
/
下的所有队列
# create a user
$ rabbitmqctl add_user aps aps
# tag the user with "administrator" for full management UI and HTTP API access
$ rabbitmqctl set_user_tags aps administrator
# 允许 aps 用户读写默认 vhost / 下所有的队列
$ rabbitmqctl set_permissions -p "/" "aps" ".*" ".*" ".*"
说明:如果全部配置完成后,再修改主机名,那么在重启rabbitmq-server服务之后,会自动生成新的配置,用户、权限、队列会丢失,需要重新配置。
四、创建集群
- 复制其中一台主机的
cookie
信息到其他节点的/var/lib/rabbitmq/.erlang.cookie
,erlang 各个节点使用cookie
实现互信访问
$ cat /var/lib/rabbitmq/.erlang.cookie
LSCWGATRVCIWVDCJHAXB
node218
、node219
均为正常启动状态(systemctl start rabbitmq-server),停止node218
上的 rabbitmq 应用,为节点加入集群做准备
$ rabbitmqctl stop_app
- 以在
node218
主机上执行以下命令为例,首先重置node218
本身的配置,加入集群后以node219
的配置为准
$ rabbitmqctl reset
- 执行以下命令,将
node218
加入node219
所在的集群,
$ rabbitmqctl join_cluster rabbit@node219
- 启动
node218
上的 rabbimtmq 应用
$ rabbitmqctl start_app
- 检查集群配置信息。在
node218
成功将node219
加入集群后,在node219
同样可以看到更新后的集群信息
$ rabbitmqctl cluster_status
Cluster status of node rabbit@node218 ...
Basics
Cluster name: rabbit@node218
Disk Nodes
rabbit@node218
rabbit@node219
Running Nodes
rabbit@node218
rabbit@node219
Versions
rabbit@node218: RabbitMQ 3.10.9 on Erlang 25.1.1
rabbit@node219: RabbitMQ 3.10.9 on Erlang 25.1.1
Maintenance status
Node: rabbit@node218, status: not under maintenance
Node: rabbit@node219, status: not under maintenance
Alarms
(none)
Network Partitions
(none)
Listeners
Node: rabbit@node218, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@node218, interface: [::], port: 15672, protocol: http, purpose: HTTP API
Node: rabbit@node218, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Node: rabbit@node219, interface: [::], port: 15672, protocol: http, purpose: HTTP API
Node: rabbit@node219, interface: [::], port: 25672, protocol: clustering, purpose: inter-node and CLI tool communication
Node: rabbit@node219, interface: [::], port: 5672, protocol: amqp, purpose: AMQP 0-9-1 and AMQP 1.0
Feature flags
Flag: classic_mirrored_queue_version, state: enabled
Flag: classic_queue_type_delivery_support, state: enabled
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
五、在集群中配置经典队列镜像
由于本次只有两节点服务器,所以选择了经典队列镜像,如果有3台或以上的节点,建议选择RabbitMQ的Quorum Queues,毕竟官方文档一直在说,经典队列镜像将在未来废弃。原因是:RabbitMQ 中的经典镜像队列存在技术限制,因此难以提供可理解的保证和明确的故障处理语义。某些故障场景可能导致镜像队列过早确认消息,从而可能导致数据丢失。
# 配置fanout.A队列做镜像
$ rabbitmqctl set_policy "fanout.A_test" "fanout.A" '{"ha-sync-mode":"automatic", "ha-mode":"exactly", "ha-params":2}'
# 配置所有mirror开头的队列做镜像
$ rabbitmqctl set_policy "mirror_policy" "^mirror." '{"ha-sync-mode":"automatic", "ha-mode":"exactly", "ha-params":2}'