MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

RabbitMQ的集群搭建与运维

2022-08-057.3k 阅读

RabbitMQ 集群搭建

环境准备

在搭建 RabbitMQ 集群之前,需要准备以下环境:

  1. 操作系统:推荐使用 Linux 系统,本文以 CentOS 7 为例进行演示。
  2. Erlang 环境:RabbitMQ 是基于 Erlang 开发的,因此需要先安装 Erlang。可以通过以下步骤在 CentOS 7 上安装 Erlang:
    • 配置 Erlang 官方 Yum 源。创建文件 /etc/yum.repos.d/rabbitmq_erlang.repo,内容如下:
[rabbitmq_erlang]
name=rabbitmq_erlang
baseurl=https://packagecloud.io/rabbitmq/erlang/el/7/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/rabbitmq/erlang/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
- 安装 Erlang:`yum install erlang -y`

3. RabbitMQ 安装包:可以从 RabbitMQ 官方网站下载适合你系统的安装包。在 CentOS 7 上,可以使用 Yum 安装: - 配置 RabbitMQ 官方 Yum 源。创建文件 /etc/yum.repos.d/rabbitmq.repo,内容如下:

[rabbitmq]
name=rabbitmq
baseurl=https://packagecloud.io/rabbitmq/rabbitmq-server/el/7/$basearch
repo_gpgcheck=1
gpgcheck=0
enabled=1
gpgkey=https://packagecloud.io/rabbitmq/rabbitmq-server/gpgkey
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
metadata_expire=300
- 安装 RabbitMQ:`yum install rabbitmq-server -y`

单机多节点集群搭建

  1. 复制 RabbitMQ 配置文件和数据目录:假设 RabbitMQ 安装在 /usr/lib/rabbitmq,数据目录默认在 /var/lib/rabbitmq。以搭建三个节点的集群为例,首先停止 RabbitMQ 服务:systemctl stop rabbitmq-server
    • 复制配置文件和数据目录,创建节点 1:
cp -r /var/lib/rabbitmq /var/lib/rabbitmq1
sed -i 's#/var/lib/rabbitmq#/var/lib/rabbitmq1#g' /var/lib/rabbitmq1/mnesia/rabbit@localhost.plist
- 创建节点 2:
cp -r /var/lib/rabbitmq /var/lib/rabbitmq2
sed -i 's#/var/lib/rabbitmq#/var/lib/rabbitmq2#g' /var/lib/rabbitmq2/mnesia/rabbit@localhost.plist
- 创建节点 3:
cp -r /var/lib/rabbitmq /var/lib/rabbitmq3
sed -i 's#/var/lib/rabbitmq#/var/lib/rabbitmq3#g' /var/lib/rabbitmq3/mnesia/rabbit@localhost.plist
  1. 修改节点配置文件:在每个节点的 RabbitMQ 配置目录(默认为 /etc/rabbitmq)下创建 rabbitmq.config 文件。
    • 节点 1 的 rabbitmq.config 内容:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@localhost1'], disc}}
    ]}
].
- 节点 2 的 `rabbitmq.config` 内容:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@localhost1'], disc}}
    ]}
].
- 节点 3 的 `rabbitmq.config` 内容:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@localhost1'], disc}}
    ]}
].

这里假设节点 1 的节点名称为 rabbit@localhost1,节点 2 为 rabbit@localhost2,节点 3 为 rabbit@localhost3。并且都以磁盘节点的形式加入到以 rabbit@localhost1 为主的集群中。磁盘节点会将集群信息持久化到磁盘,保证重启后集群信息不丢失。 3. 启动节点并加入集群: - 启动节点 1:

RABBITMQ_NODE_PORT=5673 RABBITMQ_MNESIA_DIR=/var/lib/rabbitmq1/mnesia RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq1 rabbitmq-server start

这里通过环境变量指定了节点的端口(默认 5672,这里改为 5673 避免冲突)、Mnesia 数据目录和配置文件。 - 启动节点 2 并加入集群:

RABBITMQ_NODE_PORT=5674 RABBITMQ_MNESIA_DIR=/var/lib/rabbitmq2/mnesia RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq2 rabbitmq-server start
rabbitmqctl -n rabbit@localhost2 stop_app
rabbitmqctl -n rabbit@localhost2 join_cluster rabbit@localhost1
rabbitmqctl -n rabbit@localhost2 start_app

首先启动节点 2,然后停止节点 2 的 RabbitMQ 应用,使用 join_cluster 命令将其加入到节点 1 的集群中,最后再启动节点 2 的 RabbitMQ 应用。 - 启动节点 3 并加入集群:

RABBITMQ_NODE_PORT=5675 RABBITMQ_MNESIA_DIR=/var/lib/rabbitmq3/mnesia RABBITMQ_CONFIG_FILE=/etc/rabbitmq/rabbitmq3 rabbitmq-server start
rabbitmqctl -n rabbit@localhost3 stop_app
rabbitmqctl -n rabbit@localhost3 join_cluster rabbit@localhost1
rabbitmqctl -n rabbit@localhost3 start_app

同样的步骤将节点 3 加入到集群中。

多机集群搭建

  1. 主机配置:假设有三台服务器,IP 分别为 192.168.1.100192.168.1.101192.168.1.102。在每台机器上安装好 Erlang 和 RabbitMQ,并配置好主机名与 IP 的映射。在 /etc/hosts 文件中添加如下内容:
192.168.1.100 rabbit1
192.168.1.101 rabbit2
192.168.1.102 rabbit3
  1. 配置 RabbitMQ 节点
    • rabbit1 上,修改 /etc/rabbitmq/rabbitmq.config 文件:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@rabbit1'], disc}}
    ]}
].

然后启动 RabbitMQ:systemctl start rabbitmq-server - 在 rabbit2 上,修改 /etc/rabbitmq/rabbitmq.config 文件:

[
    {rabbit, [
        {cluster_nodes, {['rabbit@rabbit1'], disc}}
    ]}
].

启动 RabbitMQ 并加入集群:

systemctl start rabbitmq-server
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
- 在 `rabbit3` 上,修改 `/etc/rabbitmq/rabbitmq.config` 文件:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@rabbit1'], disc}}
    ]}
].

启动 RabbitMQ 并加入集群:

systemctl start rabbitmq-server
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app
  1. 配置跨机器通信:RabbitMQ 集群节点之间通过 Erlang 分布式协议进行通信,需要配置节点之间的认证。可以使用 Erlang cookie 来实现认证。在所有节点上,确保 /var/lib/rabbitmq/.erlang.cookie 文件内容一致。可以将 rabbit1 上的 .erlang.cookie 文件复制到其他节点:
scp /var/lib/rabbitmq/.erlang.cookie root@rabbit2:/var/lib/rabbitmq/
scp /var/lib/rabbitmq/.erlang.cookie root@rabbit3:/var/lib/rabbitmq/

然后修改文件权限:

chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie
chmod 400 /var/lib/rabbitmq/.erlang.cookie

RabbitMQ 集群运维

集群状态查看

  1. 使用 rabbitmqctl 命令:在任意一个节点上,可以使用 rabbitmqctl cluster_status 命令查看集群状态。例如:
rabbitmqctl cluster_status

输出结果类似如下:

Cluster status of node rabbit@rabbit1...
[{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2,rabbit@rabbit3]}]},
 {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]},
 {cluster_name,<<"rabbit@rabbit1">>},
 {partitions,[]},
 {alarms,[{rabbit@rabbit1,[]},
         {rabbit@rabbit2,[]},
         {rabbit@rabbit3,[]}]}]

这里可以看到集群中的节点列表(包括磁盘节点)、运行中的节点、集群名称、分区情况以及各节点的警报信息。 2. 使用 RabbitMQ 管理界面:首先需要开启 RabbitMQ 管理插件:rabbitmq-plugins enable rabbitmq_management。然后通过浏览器访问 http://rabbit1:15672(假设 rabbit1 是集群中的一个节点),使用默认用户名 guest 和密码 guest(生产环境建议修改)登录。在管理界面的 Overview 页面,可以看到集群的整体状态,包括节点状态、队列数量、消息总数等信息。在 Nodes 页面,可以查看每个节点的详细信息,如内存使用、磁盘空间、网络连接等。

节点维护

  1. 节点重启:如果需要重启某个节点,例如 rabbit@rabbit2,首先在该节点上停止 RabbitMQ 应用:rabbitmqctl stop_app。然后进行系统重启等操作,完成后再启动 RabbitMQ 应用:rabbitmqctl start_app。在重启过程中,集群中的其他节点会继续提供服务,已有的队列和消息不会丢失(前提是节点为磁盘节点)。
  2. 节点移除:如果要移除一个节点,例如 rabbit@rabbit3,首先在该节点上停止 RabbitMQ 应用:rabbitmqctl stop_app。然后在集群中的其他节点上执行移除操作,例如在 rabbit@rabbit1 上执行:rabbitmqctl forget_cluster_node rabbit@rabbit3。最后可以在 rabbit@rabbit3 上卸载 RabbitMQ 相关软件。
  3. 节点添加:如果要添加一个新节点,例如新机器 192.168.1.103,首先在该机器上安装 Erlang 和 RabbitMQ,配置好主机名与 IP 映射,确保 .erlang.cookie 文件与集群中其他节点一致。然后修改 /etc/rabbitmq/rabbitmq.config 文件,配置加入现有集群:
[
    {rabbit, [
        {cluster_nodes, {['rabbit@rabbit1'], disc}}
    ]}
].

启动 RabbitMQ 并加入集群:

systemctl start rabbitmq-server
rabbitmqctl stop_app
rabbitmqctl join_cluster rabbit@rabbit1
rabbitmqctl start_app

队列和消息管理

  1. 队列操作
    • 创建队列:可以使用 RabbitMQ 客户端库在代码中创建队列。以 Python 的 pika 库为例:
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('rabbit1'))
channel = connection.channel()
channel.queue_declare(queue='test_queue')
connection.close()
- **删除队列**:同样使用 `pika` 库:
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('rabbit1'))
channel = connection.channel()
channel.queue_delete(queue='test_queue')
connection.close()
- **查看队列状态**:在 RabbitMQ 管理界面的 `Queues` 页面,可以查看每个队列的详细信息,如消息数量、消费者数量、是否持久化等。也可以使用 `rabbitmqctl list_queues` 命令查看所有队列及其消息数量:
rabbitmqctl list_queues
  1. 消息操作
    • 发送消息:使用 pika 库发送消息到队列:
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('rabbit1'))
channel = connection.channel()
channel.queue_declare(queue='test_queue')
message = 'Hello, RabbitMQ!'
channel.basic_publish(exchange='', routing_key='test_queue', body=message)
print(" [x] Sent 'Hello, RabbitMQ!'")
connection.close()
- **接收消息**:使用 `pika` 库接收队列中的消息:
import pika


def callback(ch, method, properties, body):
    print(" [x] Received %r" % body)


connection = pika.BlockingConnection(pika.ConnectionParameters('rabbit1'))
channel = connection.channel()
channel.queue_declare(queue='test_queue')
channel.basic_consume(queue='test_queue', on_message_callback=callback, auto_ack=True)
print(' [*] Waiting for messages. To exit press CTRL+C')
channel.start_consuming()

故障处理

  1. 节点故障:如果一个节点发生故障(例如硬件故障、软件崩溃等),集群中的其他节点会自动检测到。如果故障节点是磁盘节点,且集群中还有其他磁盘节点,集群仍然可以正常工作。当故障节点恢复后,可以重新加入集群。如果故障节点是唯一的磁盘节点,且没有备份,可能会导致部分队列和消息丢失(非持久化的队列和消息肯定丢失,持久化的队列和消息也可能丢失)。此时可以尝试从备份中恢复数据,或者根据业务需求重新创建队列和处理消息。
  2. 网络故障:网络故障可能导致集群节点之间通信中断,形成网络分区。RabbitMQ 可以通过配置来处理网络分区情况。例如,可以设置 net_ticktime 参数来调整节点之间的心跳检测时间。在 rabbitmq.config 文件中添加:
[
    {rabbit, [
        {net_ticktime, 60}
    ]}
].

这里将心跳检测时间设置为 60 秒。当网络分区发生时,RabbitMQ 会根据配置的策略来处理,例如自动合并分区或者等待人工干预。

性能优化

  1. 内存优化:RabbitMQ 使用内存来缓存队列中的消息和元数据。可以通过调整 vm_memory_high_watermark 参数来控制 RabbitMQ 使用的内存上限。在 rabbitmq.config 文件中添加:
[
    {rabbit, [
        {vm_memory_high_watermark, 0.4}
    ]}
].

这里将内存上限设置为系统内存的 40%。当 RabbitMQ 使用的内存达到这个上限时,会采取一些措施,如停止接收新消息、将消息交换到磁盘等。 2. 磁盘优化:如果队列中的消息量很大,可能需要优化磁盘 I/O。可以将 RabbitMQ 的数据目录挂载到高性能磁盘(如 SSD)上。同时,可以调整 disk_free_limit 参数来设置磁盘空间的下限。在 rabbitmq.config 文件中添加:

[
    {rabbit, [
        {disk_free_limit, "50MB"}
    ]}
].

当磁盘空间低于这个限制时,RabbitMQ 会停止接收新消息,以防止磁盘被写满。 3. 连接优化:如果有大量的客户端连接到 RabbitMQ 集群,可以通过设置 tcp_listen_options 来优化 TCP 连接。在 rabbitmq.config 文件中添加:

[
    {rabbit, [
        {tcp_listen_options, [
            {backlog, 128},
            {nodelay, true}
        ]}
    ]}
].

这里设置了 TCP 连接的 backlog 为 128,启用了 TCP_NODELAY 选项,以提高连接性能。

安全配置

  1. 用户管理:默认的 guest 用户只允许本地连接,生产环境中应该创建新的用户并设置强密码。使用 rabbitmqctl add_user 命令创建用户,例如:
rabbitmqctl add_user myuser mypassword

然后设置用户权限,例如允许用户访问 / 虚拟主机,并具有所有权限:

rabbitmqctl set_permissions -p / myuser ".*" ".*" ".*"
  1. 虚拟主机管理:虚拟主机可以将 RabbitMQ 服务器分割成多个独立的环境。使用 rabbitmqctl add_vhost 命令创建虚拟主机,例如:
rabbitmqctl add_vhost myvhost

然后可以将用户与虚拟主机关联,并设置权限。 3. SSL/TLS 配置:为了保证数据传输的安全性,可以配置 RabbitMQ 使用 SSL/TLS 协议。首先需要生成 SSL 证书和密钥,例如使用 OpenSSL:

openssl req -new -x509 -days 365 -nodes -out /etc/rabbitmq/rabbitmq.crt -keyout /etc/rabbitmq/rabbitmq.key

然后在 /etc/rabbitmq/rabbitmq.config 文件中添加 SSL 配置:

[
    {rabbit, [
        {ssl_listeners, [5671]},
        {ssl_options, [
            {cacertfile,"/etc/rabbitmq/ca.crt"},
            {certfile,"/etc/rabbitmq/rabbitmq.crt"},
            {keyfile,"/etc/rabbitmq/rabbitmq.key"},
            {verify,verify_peer},
            {fail_if_no_peer_cert,true}
        ]}
    ]}
].

这里配置了 RabbitMQ 在 5671 端口监听 SSL 连接,并设置了证书和验证选项。客户端连接时需要使用相应的 SSL 配置。

通过以上步骤,你可以搭建一个 RabbitMQ 集群,并进行有效的运维管理,确保其在生产环境中稳定、高效、安全地运行。