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