RabbitMQ 集群降配

这里写自定义目录标题

    • 摘要
    • 检查状态
      • [1. 检查 RabbitMQ 服务状态](#1. 检查 RabbitMQ 服务状态)
      • [2. 检查 RabbitMQ 端口监听](#2. 检查 RabbitMQ 端口监听)
      • [3. 检查 RabbitMQ 管理插件是否启用](#3. 检查 RabbitMQ 管理插件是否启用)
      • [4. 检查开机自启状态](#4. 检查开机自启状态)
      • [5. 确认集群高可用性](#5. 确认集群高可用性)
      • [6. 检查使用该集群的服务是否做了断开重连](#6. 检查使用该集群的服务是否做了断开重连)
    • 实操
      • [1. 负载均衡配置](#1. 负载均衡配置)
      • [2. 逐个节点降配(滚动操作)](#2. 逐个节点降配(滚动操作))
        • [2.1 停止 RabbitMQ 服务](#2.1 停止 RabbitMQ 服务)
        • [2.2 调整 ECS 配置](#2.2 调整 ECS 配置)
        • [2.3 恢复节点并重新加入集群](#2.3 恢复节点并重新加入集群)
        • [2.4 恢复负载均衡流量](#2.4 恢复负载均衡流量)
      • [3. 全局监控与验证](#3. 全局监控与验证)
      • [4. 降配后优化(可选)](#4. 降配后优化(可选))
      • 风险点与应对
      • 总结
    • 命令说明
      • [查看集群状态命令 rabbitmqctl cluster_status](#查看集群状态命令 rabbitmqctl cluster_status)
        • [1. 集群节点状态](#1. 集群节点状态)
        • [2. 网络分区](#2. 网络分区)
        • [3. 告警状态](#3. 告警状态)
        • [4. 集群名称](#4. 集群名称)
        • 健康状态总结
        • 进一步验证建议
          • [1. 检查队列镜像状态](#1. 检查队列镜像状态)
          • [2. 检查资源使用情况](#2. 检查资源使用情况)
          • [3. 检查日志](#3. 检查日志)
          • [4. 监控连接数](#4. 监控连接数)
      • [查看节点同步状态 rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids](#查看节点同步状态 rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids)
      • 删除队列
        • [在 RabbitMQ 中执行删除队列(`delete_queue`)操作时,如果出现 `Access refused` 错误,通常是由于权限问题导致的。以下是可能的原因及解决方法:](#在 RabbitMQ 中执行删除队列(delete_queue)操作时,如果出现 Access refused 错误,通常是由于权限问题导致的。以下是可能的原因及解决方法:)

摘要

背景 :2025年云成本优化仍是技术团队的核心命题。当前需对遗留架构进行精细化治理,其中由前任架构师设计的RabbitMQ集群成为重点优化对象。该集群采用经典高可用架构,由3台阿里云ECS实例构成核心节点,并通过负载均衡(SLB)实现流量分发。然而,经监控分析发现,节点资源利用率长期低于40%,存在显著的配置冗余。在保障业务连续性的前提下,需通过降配调优实现成本节约。

ECS 配置 :8C16G,CPU利用率 峰值18%, 内存峰值 25%
降配目标 :平滑的将ECS节点降配至 2C8G

检查状态

1. 检查 RabbitMQ 服务状态

使用 systemctl 命令查看服务是否正在运行:

bash 复制代码
sudo systemctl status rabbitmq-server
  • 输出结果
    • 如果显示 active (running),表示服务已启动。
    • 如果显示 inactive (dead),表示服务未运行。

2. 检查 RabbitMQ 端口监听

RabbitMQ 默认监听 5672(AMQP 协议)和 15672(管理界面)端口:

bash 复制代码
# 使用 netstat 或 ss 命令检查端口
sudo netstat -tuln | grep -E '5672|15672'
# 或
sudo ss -tuln | grep -E '5672|15672'
  • 输出结果 :如果有 LISTEN 状态的端口,说明服务正常。

3. 检查 RabbitMQ 管理插件是否启用

若需通过 Web 界面管理 RabbitMQ,需确认管理插件是否启用:

bash 复制代码
sudo rabbitmq-plugins list
  • 输出结果 :查找 rabbitmq_management 是否标记为 [E*](已启用)。

4. 检查开机自启状态

确认 RabbitMQ 是否设置为开机自启:

bash 复制代码
sudo systemctl is-enabled rabbitmq-server
  • 输出结果
    • enabled:已设置开机自启。
    • disabled:未设置开机自启(可通过 sudo systemctl enable rabbitmq-server 启用)。

5. 确认集群高可用性

  • 镜像队列配置 :确保所有业务队列已配置镜像策略(如 ha-mode: all 或指定副本数),避免单节点故障导致消息丢失。

    bash 复制代码
    # 查看当前策略
    rabbitmqctl list_policies
    # 示例:设置所有队列在3个节点镜像
    rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
  • 集群状态健康 :确认所有节点状态为 running,且无网络分区问题。

    bash 复制代码
    rabbitmqctl cluster_status

6. 检查使用该集群的服务是否做了断开重连

实操

1. 负载均衡配置

  • 设置待降配节点的权重:在负载均衡(如 SLB)中暂时设置待操作节点的流量权重为0,确保降配期间流量仅路由到其他节点。

2. 逐个节点降配(滚动操作)

2.1 停止 RabbitMQ 服务
bash 复制代码
sudo systemctl stop rabbitmq-server
  • 验证节点离线 :检查集群状态,确认该节点已标记为 down

    bash 复制代码
    rabbitmqctl cluster_status
2.2 调整 ECS 配置
  • 关机 ECS
  • 降配操作:通过 ECS 控制台或 API 调整实例规格(CPU/内存)。
  • 重启 ECS(如需):若配置变更需要重启,确保重启后网络和存储正常挂载。
2.3 恢复节点并重新加入集群
  • 启动 RabbitMQ

    bash 复制代码
    sudo systemctl start rabbitmq-server
  • 重新加入集群 :如果节点因 IP 或主机名变化无法自动加入,需手动操作(一般不需要重新加入)

    bash 复制代码
    # 在新节点上重置 RabbitMQ 并重新加入集群
    rabbitmqctl stop_app
    rabbitmqctl reset
    rabbitmqctl join_cluster rabbit@<主节点主机名>
    rabbitmqctl start_app
  • 验证集群状态 :确保节点状态为 running,且队列镜像同步完成。

2.4 恢复负载均衡流量
  • 将节点权重恢复,观察健康检查状态。

3. 全局监控与验证

  • 业务监控:观察消息堆积、消费延迟、连接数等指标。

  • 集群同步状态 :检查镜像队列同步进度。

    bash 复制代码
    rabbitmqctl list_queues name messages_ready messages_unacknowledged
  • 日志检查 :排查降配节点是否有异常报错。

    bash 复制代码
    tail -f /var/log/rabbitmq/rabbit@*.log

4. 降配后优化(可选)

  • 调整内存阈值 :根据新配置优化 RabbitMQ 内存限制(vm_memory_high_watermark)。
  • 磁盘空间监控:确保降配后的磁盘容量足够(RabbitMQ 默认需至少 50MB 剩余空间)。

风险点与应对

  1. 同步延迟:降配节点重启后,若队列数据量大,同步时间可能较长。建议在低峰期操作。
  2. 配置兼容性:确保新规格满足 RabbitMQ 最低要求(如内存不低于 1GB)。
  3. 网络波动:降配期间若节点 IP 变化,需更新集群节点列表和负载均衡配置。

总结

通过 逐节点滚动降配 + 负载均衡流量切换,可实现业务无感知。关键点在于确保镜像队列冗余、集群健康状态,以及操作顺序的严谨性。建议先在测试环境模拟流程,再在生产环境执行。

命令说明

查看集群状态命令 rabbitmqctl cluster_status

输出结果解析

bash 复制代码
Cluster status of node rabbit@rabbitmq-prod-03 ...
[{nodes,[{disc,['rabbit@rabbitmq-prod-01','rabbit@rabbitmq-prod-02',
                'rabbit@rabbitmq-prod-03']}]},
 {running_nodes,['rabbit@rabbitmq-prod-02','rabbit@rabbitmq-prod-01',
                 'rabbit@rabbitmq-prod-03']},
 {cluster_name,<<"rabbit@rabbitmq-prod-01">>},
 {partitions,[]},
 {alarms,[{'rabbit@rabbitmq-prod-02',[]},
          {'rabbit@rabbitmq-prod-01',[]},
          {'rabbit@rabbitmq-prod-03',[]}]}].
1. 集群节点状态
  • 所有节点均在线
    • {nodes} 列表显示集群包含 3 个磁盘节点(disc 类型):rabbit@rabbitmq-prod-01, rabbit@rabbitmq-prod-02, rabbit@rabbitmq-prod-03
    • {running_nodes} 列表显示这 3 个节点当前都在运行。
2. 网络分区
  • 无网络分区
    • {partitions,[]} 表示没有发生网络分区问题。如果存在分区,partitions 字段会列出被隔离的节点及其分区信息。
3. 告警状态
  • 无告警
    • {alarms,[{'rabbit@rabbitmq-prod-02',[]}, {'rabbit@rabbitmq-prod-01',[]}, {'rabbit@rabbitmq-prod-03',[]}]} 表明所有节点均未触发任何告警(如内存、磁盘空间不足等)。
4. 集群名称
  • 集群名称一致
    • {cluster_name,<<"rabbit@rabbitmq-prod-01">>} 显示集群的名称为 rabbit@rabbitmq-prod-01,所有节点共享同一个集群名称,表明它们属于同一集群。

健康状态总结

从上述分析来看,你的 RabbitMQ 集群处于健康状态

  1. 所有节点都在线且正常运行。
  2. 没有网络分区问题。
  3. 没有任何节点触发告警。
  4. 集群名称一致,结构完整。

进一步验证建议

虽然当前状态健康,但为了确保长期稳定运行,可以执行以下检查:

1. 检查队列镜像状态

确认队列是否在多个节点上正确镜像:

bash 复制代码
rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids
  • 确保关键队列的 slave_pidssynchronised_slave_pids 包含至少 2 个节点。
2. 检查资源使用情况

监控节点的 CPU、内存和磁盘使用率,避免因资源不足导致性能下降或告警:

bash 复制代码
# 查看磁盘剩余空间
df -h

# 查看内存使用情况
free -m

# 查看 RabbitMQ 内存使用
rabbitmqctl status | grep -A 5 "memory"
3. 检查日志

查看 RabbitMQ 日志文件,排查潜在的警告或错误:

bash 复制代码
tail -n 20 /var/log/rabbitmq/rabbit@*.log
4. 监控连接数

确保各节点的连接数在合理范围内:

bash 复制代码
rabbitmqctl list_connections --node rabbit@rabbitmq-prod-03 | grep -v "Listing" | wc -l

查看节点同步状态 rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids

命令输出解析

以下是 rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids 的输出示例:

plaintext 复制代码
name: collector_event
pid: <rabbit@rabbitmq-prod-03.1606707793.6080.60>
slave_pids: [<rabbit@rabbitmq-prod-02.1607654826.19286.68>, <rabbit@rabbitmq-prod-01.1606707802.17230.4475>]
synchronised_slave_pids: [<rabbit@rabbitmq-prod-01.1606707802.17230.4475>, <rabbit@rabbitmq-prod-02.1607654826.19286.68>]
字段含义
  1. name

    • 队列名称。例如:collector_event
  2. pid

    • 主队列所在节点的进程 ID(Process ID)。例如:<rabbit@rabbitmq-prod-03.1606707793.6080.60> 表示主队列位于 rabbit@rabbitmq-prod-03 节点。
  3. slave_pids

    • 副本队列所在的节点和进程 ID 列表。例如:
      • <rabbit@rabbitmq-prod-02.1607654826.19286.68> 表示该副本位于 rabbit@rabbitmq-prod-02
      • <rabbit@rabbitmq-prod-01.1606707802.17230.4475> 表示该副本位于 rabbit@rabbitmq-prod-01
  4. synchronised_slave_pids

    • 已完成数据同步的副本队列所在的节点和进程 ID 列表。例如:
      • <rabbit@rabbitmq-prod-01.1606707802.17230.4475><rabbit@rabbitmq-prod-02.1607654826.19286.68> 表示这两个副本已完成同步。

如何判断镜像同步完成
  1. 比较 slave_pidssynchronised_slave_pids

    • 如果 synchronised_slave_pids 包含所有 slave_pids 中的节点,则表示所有副本均已同步完成。
    • 示例分析
      • slave_pids: [<rabbit@rabbitmq-prod-02>, <rabbit@rabbitmq-prod-01>]
      • synchronised_slave_pids: [<rabbit@rabbitmq-prod-01>, <rabbit@rabbitmq-prod-02>]
      • 结论synchronised_slave_pids 包含了所有 slave_pids,说明镜像已完全同步。
  2. 检查数量是否一致

    • 如果 slave_pidssynchronised_slave_pids 的数量相同,且内容一致,则镜像同步完成。
  3. 异常情况

    • 如果 synchronised_slave_pids 为空或少于 slave_pids,则表示某些副本尚未完成同步,需等待同步完成后再继续操作。可以到管理界面queue界面查看有哪些队里没有同步完成,可点击进入队列并手动同步。

删除队列

bash 复制代码
rabbitmqctl delete_queue -p  <host>  <queue_name>
在 RabbitMQ 中执行删除队列(delete_queue)操作时,如果出现 Access refused 错误,通常是由于权限问题导致的。以下是可能的原因及解决方法:
1. 用户权限不足

RabbitMQ 的用户权限分为三类:

  • Configure:允许创建和删除队列、交换器等资源。
  • Write:允许向队列发送消息。
  • Read:允许从队列消费消息。
检查用户权限

使用以下命令查看当前用户的权限:

bash 复制代码
rabbitmqctl list_permissions -p <vhost>
  • <vhost> 是目标虚拟主机,默认为 /

  • 输出示例:

    复制代码
    Listing permissions for vhost "/" ...
    user    configure   write   read
    guest   .*          .*      .*
解决方法

确保当前用户对目标队列所在的虚拟主机具有足够的权限:

bash 复制代码
# 授予用户对虚拟主机的权限
rabbitmqctl set_permissions -p <vhost> <username> ".*" ".*" ".*"
  • <username>:当前登录 RabbitMQ 的用户名。
  • "."*:表示匹配所有资源。

2. 队列被其他消费者占用

如果队列正在被其他消费者使用(例如有活跃的连接或未确认的消息),删除操作可能会失败。

解决方法
  • 停止消费者:确保没有客户端正在消费该队列。

  • 清空队列 (可选):

    bash 复制代码
    rabbitmqadmin delete queue name=<queue_name>

    或通过管理界面清空队列。


3. 用户未绑定到正确的虚拟主机

RabbitMQ 支持多虚拟主机(vhost)。如果用户未绑定到目标队列所在的虚拟主机,也会导致权限拒绝。

检查虚拟主机

列出所有虚拟主机:

bash 复制代码
rabbitmqctl list_vhosts
解决方法

将用户添加到正确的虚拟主机,并授予权限:

bash 复制代码
# 添加用户到虚拟主机
rabbitmqctl add_user <username> <password>
rabbitmqctl set_permissions -p <vhost> <username> ".*" ".*" ".*"

相关推荐
用户8307196840822 天前
RabbitMQ vs RocketMQ 事务大对决:一个在“裸奔”,一个在“开挂”?
后端·rabbitmq·rocketmq
初次攀爬者3 天前
RabbitMQ的消息模式和高级特性
后端·消息队列·rabbitmq
初次攀爬者5 天前
ZooKeeper 实现分布式锁的两种方式
分布式·后端·zookeeper
让我上个超影吧6 天前
消息队列——RabbitMQ(高级)
java·rabbitmq
塔中妖6 天前
Windows 安装 RabbitMQ 详细教程(含 Erlang 环境配置)
windows·rabbitmq·erlang
断手当码农6 天前
Redis 实现分布式锁的三种方式
数据库·redis·分布式
初次攀爬者6 天前
Redis分布式锁实现的三种方式-基于setnx,lua脚本和Redisson
redis·分布式·后端
业精于勤_荒于稀6 天前
物流订单系统99.99%可用性全链路容灾体系落地操作手册
分布式
Ronin3056 天前
信道管理模块和异步线程模块
开发语言·c++·rabbitmq·异步线程·信道管理
Asher05096 天前
Hadoop核心技术与实战指南
大数据·hadoop·分布式