这里写自定义目录标题
- 摘要
- 检查状态
- 1. 检查 RabbitMQ 服务状态
- 2. 检查 RabbitMQ 端口监听
- 3. 检查 RabbitMQ 管理插件是否启用
- 4. 检查开机自启状态
- 5. 确认集群高可用性
- 6. 检查使用该集群的服务是否做了断开重连
- 实操
- 1. 负载均衡配置
- 2. 逐个节点降配(滚动操作)
- 2.1 停止 RabbitMQ 服务
- 2.2 调整 ECS 配置
- 2.3 恢复节点并重新加入集群
- 2.4 恢复负载均衡流量
- 3. 全局监控与验证
- 4. 降配后优化(可选)
- 风险点与应对
- 总结
- 命令说明
- 查看集群状态命令 rabbitmqctl cluster_status
- 1. 集群节点状态
- 2. 网络分区
- 3. 告警状态
- 4. 集群名称
- 健康状态总结
- 进一步验证建议
- 1. 检查队列镜像状态
- 2. 检查资源使用情况
- 3. 检查日志
- 4. 监控连接数
- 查看节点同步状态 rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids
- 字段含义
- 如何判断镜像同步完成
- 删除队列
- 在 RabbitMQ 中执行删除队列(`delete_queue`)操作时,如果出现 `Access refused` 错误,通常是由于权限问题导致的。以下是可能的原因及解决方法:
- 1. 用户权限不足
- 检查用户权限
- 解决方法
- 2. 队列被其他消费者占用
- 解决方法
- 3. 用户未绑定到正确的虚拟主机
- 检查虚拟主机
- 解决方法
摘要
背景:2025年云成本优化仍是技术团队的核心命题。当前需对遗留架构进行精细化治理,其中由前任架构师设计的RabbitMQ集群成为重点优化对象。该集群采用经典高可用架构,由3台阿里云ECS实例构成核心节点,并通过负载均衡(SLB)实现流量分发。然而,经监控分析发现,节点资源利用率长期低于40%,存在显著的配置冗余。在保障业务连续性的前提下,需通过降配调优实现成本节约。
ECS 配置:8C16G,CPU利用率 峰值18%, 内存峰值 25%
降配目标:平滑的将ECS节点降配至 2C8G
检查状态
1. 检查 RabbitMQ 服务状态
使用 systemctl
命令查看服务是否正在运行:
sudo systemctl status rabbitmq-server
- 输出结果:
- 如果显示
active (running)
,表示服务已启动。 - 如果显示
inactive (dead)
,表示服务未运行。
- 如果显示
2. 检查 RabbitMQ 端口监听
RabbitMQ 默认监听 5672
(AMQP 协议)和 15672
(管理界面)端口:
# 使用 netstat 或 ss 命令检查端口
sudo netstat -tuln | grep -E '5672|15672'
# 或
sudo ss -tuln | grep -E '5672|15672'
- 输出结果:如果有
LISTEN
状态的端口,说明服务正常。
3. 检查 RabbitMQ 管理插件是否启用
若需通过 Web 界面管理 RabbitMQ,需确认管理插件是否启用:
sudo rabbitmq-plugins list
- 输出结果:查找
rabbitmq_management
是否标记为[E*]
(已启用)。
4. 检查开机自启状态
确认 RabbitMQ 是否设置为开机自启:
sudo systemctl is-enabled rabbitmq-server
- 输出结果:
enabled
:已设置开机自启。disabled
:未设置开机自启(可通过sudo systemctl enable rabbitmq-server
启用)。
5. 确认集群高可用性
- 镜像队列配置:确保所有业务队列已配置镜像策略(如
ha-mode: all
或指定副本数),避免单节点故障导致消息丢失。# 查看当前策略 rabbitmqctl list_policies # 示例:设置所有队列在3个节点镜像 rabbitmqctl set_policy ha-all "^" '{"ha-mode":"all"}'
- 集群状态健康:确认所有节点状态为
running
,且无网络分区问题。rabbitmqctl cluster_status
6. 检查使用该集群的服务是否做了断开重连
实操
1. 负载均衡配置
- 设置待降配节点的权重:在负载均衡(如 SLB)中暂时设置待操作节点的流量权重为0,确保降配期间流量仅路由到其他节点。
2. 逐个节点降配(滚动操作)
2.1 停止 RabbitMQ 服务
sudo systemctl stop rabbitmq-server
- 验证节点离线:检查集群状态,确认该节点已标记为
down
。rabbitmqctl cluster_status
2.2 调整 ECS 配置
- 关机 ECS
- 降配操作:通过 ECS 控制台或 API 调整实例规格(CPU/内存)。
- 重启 ECS(如需):若配置变更需要重启,确保重启后网络和存储正常挂载。
2.3 恢复节点并重新加入集群
- 启动 RabbitMQ:
sudo systemctl start rabbitmq-server
- 重新加入集群:如果节点因 IP 或主机名变化无法自动加入,需手动操作(一般不需要重新加入)
# 在新节点上重置 RabbitMQ 并重新加入集群 rabbitmqctl stop_app rabbitmqctl reset rabbitmqctl join_cluster rabbit@<主节点主机名> rabbitmqctl start_app
- 验证集群状态:确保节点状态为
running
,且队列镜像同步完成。
2.4 恢复负载均衡流量
- 将节点权重恢复,观察健康检查状态。
3. 全局监控与验证
- 业务监控:观察消息堆积、消费延迟、连接数等指标。
- 集群同步状态:检查镜像队列同步进度。
rabbitmqctl list_queues name messages_ready messages_unacknowledged
- 日志检查:排查降配节点是否有异常报错。
tail -f /var/log/rabbitmq/rabbit@*.log
4. 降配后优化(可选)
- 调整内存阈值:根据新配置优化 RabbitMQ 内存限制(
vm_memory_high_watermark
)。 - 磁盘空间监控:确保降配后的磁盘容量足够(RabbitMQ 默认需至少 50MB 剩余空间)。
风险点与应对
- 同步延迟:降配节点重启后,若队列数据量大,同步时间可能较长。建议在低峰期操作。
- 配置兼容性:确保新规格满足 RabbitMQ 最低要求(如内存不低于 1GB)。
- 网络波动:降配期间若节点 IP 变化,需更新集群节点列表和负载均衡配置。
总结
通过 逐节点滚动降配 + 负载均衡流量切换,可实现业务无感知。关键点在于确保镜像队列冗余、集群健康状态,以及操作顺序的严谨性。建议先在测试环境模拟流程,再在生产环境执行。
命令说明
查看集群状态命令 rabbitmqctl cluster_status
输出结果解析
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. 检查队列镜像状态
确认队列是否在多个节点上正确镜像:
rabbitmqctl list_queues name pid slave_pids synchronised_slave_pids
- 确保关键队列的
slave_pids
和synchronised_slave_pids
包含至少 2 个节点。
2. 检查资源使用情况
监控节点的 CPU、内存和磁盘使用率,避免因资源不足导致性能下降或告警:
# 查看磁盘剩余空间
df -h
# 查看内存使用情况
free -m
# 查看 RabbitMQ 内存使用
rabbitmqctl status | grep -A 5 "memory"
3. 检查日志
查看 RabbitMQ 日志文件,排查潜在的警告或错误:
tail -n 20 /var/log/rabbitmq/rabbit@*.log
4. 监控连接数
确保各节点的连接数在合理范围内:
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
的输出示例:
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>]
字段含义
-
name
:- 队列名称。例如:
collector_event
。
- 队列名称。例如:
-
pid
:- 主队列所在节点的进程 ID(Process ID)。例如:
<rabbit@rabbitmq-prod-03.1606707793.6080.60>
表示主队列位于rabbit@rabbitmq-prod-03
节点。
- 主队列所在节点的进程 ID(Process ID)。例如:
-
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
。
- 副本队列所在的节点和进程 ID 列表。例如:
-
synchronised_slave_pids
:- 已完成数据同步的副本队列所在的节点和进程 ID 列表。例如:
<rabbit@rabbitmq-prod-01.1606707802.17230.4475>
和<rabbit@rabbitmq-prod-02.1607654826.19286.68>
表示这两个副本已完成同步。
- 已完成数据同步的副本队列所在的节点和进程 ID 列表。例如:
如何判断镜像同步完成
-
比较
slave_pids
和synchronised_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
,说明镜像已完全同步。
- 如果
-
检查数量是否一致:
- 如果
slave_pids
和synchronised_slave_pids
的数量相同,且内容一致,则镜像同步完成。
- 如果
-
异常情况:
- 如果
synchronised_slave_pids
为空或少于slave_pids
,则表示某些副本尚未完成同步,需等待同步完成后再继续操作。可以到管理界面queue界面查看有哪些队里没有同步完成,可点击进入队列并手动同步。
- 如果
删除队列
rabbitmqctl delete_queue -p <host> <queue_name>
在 RabbitMQ 中执行删除队列(delete_queue
)操作时,如果出现 Access refused
错误,通常是由于权限问题导致的。以下是可能的原因及解决方法:
1. 用户权限不足
RabbitMQ 的用户权限分为三类:
- Configure:允许创建和删除队列、交换器等资源。
- Write:允许向队列发送消息。
- Read:允许从队列消费消息。
检查用户权限
使用以下命令查看当前用户的权限:
rabbitmqctl list_permissions -p <vhost>
<vhost>
是目标虚拟主机,默认为/
。- 输出示例:
Listing permissions for vhost "/" ... user configure write read guest .* .* .*
解决方法
确保当前用户对目标队列所在的虚拟主机具有足够的权限:
# 授予用户对虚拟主机的权限
rabbitmqctl set_permissions -p <vhost> <username> ".*" ".*" ".*"
<username>
:当前登录 RabbitMQ 的用户名。"."*
:表示匹配所有资源。
2. 队列被其他消费者占用
如果队列正在被其他消费者使用(例如有活跃的连接或未确认的消息),删除操作可能会失败。
解决方法
- 停止消费者:确保没有客户端正在消费该队列。
- 清空队列(可选):
或通过管理界面清空队列。rabbitmqadmin delete queue name=<queue_name>
3. 用户未绑定到正确的虚拟主机
RabbitMQ 支持多虚拟主机(vhost
)。如果用户未绑定到目标队列所在的虚拟主机,也会导致权限拒绝。
检查虚拟主机
列出所有虚拟主机:
rabbitmqctl list_vhosts
解决方法
将用户添加到正确的虚拟主机,并授予权限:
# 添加用户到虚拟主机
rabbitmqctl add_user <username> <password>
rabbitmqctl set_permissions -p <vhost> <username> ".*" ".*" ".*"