RabbitMQ 消息队列完全教程 / 第 15 章:故障排查
第 15 章:故障排查
本章汇总 RabbitMQ 生产环境中最常见的问题及其排查方法,帮助你快速定位和解决问题。
15.1 故障排查通用流程
发现异常
│
├── 1. 查看系统日志 /var/log/rabbitmq/*.log
├── 2. 检查管理界面概览
├── 3. 运行健康检查
├── 4. 检查资源使用(内存、磁盘、文件描述符)
├── 5. 检查连接/通道/队列状态
└── 6. 根据错误信息定位问题
常用诊断命令
# 集群状态
rabbitmqctl status
rabbitmqctl cluster_status
# 健康检查
rabbitmq-diagnostics check_running
rabbitmq-diagnostics check_local_alarms
rabbitmq-diagnostics check_port_connectivity
rabbitmq-diagnostics check_if_node_is_quorum_critical
# 列出资源
rabbitmqctl list_queues name messages consumers memory
rabbitmqctl list_connections name state channels
rabbitmqctl list_channels consumer_count messages_unacknowledged
# 日志
rabbitmq-diagnostics log_tail --since 1h
tail -f /var/log/rabbitmq/[email protected]
15.2 连接问题
问题一:连接被拒绝
症状: Connection refused 或 AMQPConnectionError
排查步骤:
# 1. 检查服务是否运行
systemctl status rabbitmq-server
rabbitmqctl status
# 2. 检查端口监听
ss -tlnp | grep 5672
netstat -tlnp | grep 5672
# 3. 检查防火墙
iptables -L -n | grep 5672
firewall-cmd --list-ports
# 4. 检查配置
cat /etc/rabbitmq/rabbitmq.conf | grep listeners
常见原因及解决方案:
| 原因 | 解决方案 |
|---|---|
| 服务未启动 | systemctl start rabbitmq-server |
| 端口被占用 | ss -tlnp | grep 5672 查找并释放 |
| 防火墙阻止 | firewall-cmd --add-port=5672/tcp --permanent |
| 监听地址限制 | 检查 listeners.tcp.default 配置 |
| Docker 端口未映射 | 检查 -p 5672:5672 参数 |
问题二:认证失败
症状: ACCESS_REFUSED - Login was refused using authentication mechanism PLAIN
# 检查用户是否存在
rabbitmqctl list_users
# 检查用户权限
rabbitmqctl list_permissions
# 重置密码
rabbitmqctl change_password username newpassword
# guest 用户远程访问被拒绝
# 解决: 创建新用户或修改 loopback_users.guest = false(不推荐)
rabbitmqctl add_user admin admin123
rabbitmqctl set_user_tags admin administrator
rabbitmqctl set_permissions -p / admin ".*" ".*" ".*"
问题三:连接数过多
症状: 新连接被拒绝,日志出现 connection_closed_abruptly
# 查看连接数
rabbitmqctl list_connections name peer_host state channels | wc -l
# 查看每个 IP 的连接数
rabbitmqctl list_connections peer_host | sort | uniq -c | sort -rn
# 关闭特定主机的连接
rabbitmqctl close_connection "connection_id" "reason"
解决方案:
| 措施 | 说明 |
|---|---|
| 使用连接池 | 每个应用实例使用一个连接 + 多个 Channel |
| 设置连接限制 | channel_max = 2048 |
| 设置心跳 | heartbeat = 60 |
| 及时关闭空闲连接 | 客户端设置 connection_timeout |
15.3 内存告警
症状
- 日志出现
vm_memory_high_watermark set - 消息发布被阻塞
- 连接显示
blocked状态
排查
# 查看内存使用
rabbitmqctl status | grep mem_used
# 查看内存告警
rabbitmqctl status | grep alarms
# 查看阻塞的连接
rabbitmqctl list_connections name state | grep blocked
# 查看队列内存使用
rabbitmqctl list_queues name memory messages | sort -k3 -rn | head -20
解决方案
# 1. 增加内存阈值(临时)
rabbitmqctl set_vm_memory_high_watermark 0.7
# 2. 永久配置
# /etc/rabbitmq/rabbitmq.conf
vm_memory_high_watermark.relative = 0.6
vm_memory_high_watermark_paging_ratio = 0.75
# 3. 清理大队列
rabbitmqctl purge_queue queue_name
# 4. 扩容内存
# 增加服务器内存或使用更多节点分担负载
内存优化建议
| 措施 | 说明 |
|---|---|
| 使用仲裁队列 | 内存管理更高效 |
| 设置队列长度限制 | x-max-length / x-max-length-bytes |
| 使用惰性队列 | 消息优先写磁盘 |
| 减少消息大小 | 避免发送大消息 |
| 及时消费 | 避免消息长期堆积 |
15.4 磁盘告警
症状
- 日志出现
disk_free_limit alarm - 消息发布被阻塞
排查
# 查看磁盘使用
df -h
rabbitmqctl status | grep disk_free
# 查看告警状态
rabbitmqctl status | grep alarms
# 查看队列占用
rabbitmqctl list_queues name messages durable | sort -k2 -rn | head -20
解决方案
# 1. 调整磁盘阈值(临时)
rabbitmqctl set_disk_free_limit 1GB
# 2. 永久配置
disk_free_limit.absolute = 2GB
# 3. 清理数据
# 清空指定队列
rabbitmqctl purge_queue queue_name
# 删除不用的队列
rabbitmqctl delete_queue queue_name
# 4. 扩容磁盘
# 增加磁盘空间或迁移数据目录
15.5 网络分区
症状
cluster_status中显示partitions非空- 部分节点之间无法通信
排查
# 检查网络分区
rabbitmqctl cluster_status | grep partitions
# 检查节点间连通性
rabbitmq-diagnostics check_port_connectivity
# 查看日志中的网络相关错误
grep -i "network\|partition\|net_ticktime" /var/log/rabbitmq/*.log
恢复步骤
# 方案 1: 自动恢复(pause_minority 配置下)
# 等待网络恢复后节点自动加入
# 方案 2: 手动恢复
# 1. 选择数据最新的节点作为主节点
# 2. 在其他节点上执行:
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@primary_node
rabbitmqctl start_app
# 方案 3: 强制重置(最后手段)
rabbitmqctl force_reset
预防措施
# 配置分区处理策略
cluster_partition_handling = pause_minority
# 调整网络检测超时(默认 60s)
net_ticktime = 120
# 使用仲裁队列(不受网络分区影响数据一致性)
15.6 慢消费者
症状
- 队列中消息持续堆积
messages_unacknowledged持续增长- 消费者连接正常但处理缓慢
排查
# 查看未确认消息
rabbitmqctl list_queues name messages messages_unacknowledged consumers
# 查看消费者的预取设置
rabbitmqctl list_channels prefetch_count consumer_count messages_unacknowledged
# 查看消费者处理速率(通过管理 API)
curl -u admin:admin123 http://localhost:15672/api/queues/%2F/queue_name | \
jq '{messages, messages_ready, messages_unacknowledged, consumer_details}'
解决方案
| 措施 | 说明 |
|---|---|
| 增加消费者实例 | 水平扩展消费者 |
| 调整 prefetch_count | 根据处理速度调整预取值 |
| 优化处理逻辑 | 减少每条消息的处理时间 |
| 使用异步处理 | 消费后立即确认,异步执行业务逻辑 |
| 检查消费者是否阻塞 | 可能在等待数据库/外部服务 |
| 设置消费超时 | 消费者处理超时后重新投递消息 |
# 设置合理的预取值
channel.basic_qos(prefetch_count=10) # 根据处理速度调整
# 消费者处理超时
import signal
def timeout_handler(signum, frame):
raise TimeoutError("Message processing timeout")
def callback(ch, method, properties, body):
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(30) # 30 秒超时
try:
process_message(body)
ch.basic_ack(delivery_tag=method.delivery_tag)
except TimeoutError:
ch.basic_nack(delivery_tag=method.delivery_tag, requeue=True)
finally:
signal.alarm(0)
15.7 消息丢失排查
消息丢失的可能阶段
Producer ──1──> Broker ──2──> Queue ──3──> Consumer
│ │
网络/确认 持久化/存储
| 阶段 | 排查点 | 确认方法 |
|---|---|---|
| 1. 生产端 | 是否启用了 Publisher Confirm | 代码检查 |
| 2. Broker 存储 | Exchange/Queue/Message 是否持久化 | 配置检查 |
| 3. 消费端 | 是否启用手动 ACK | 代码检查 |
验证消息持久化
# 检查队列是否持久化
rabbitmqctl list_queues name durable
# 检查消息数量
rabbitmqctl list_queues name messages
# 重启 RabbitMQ 后检查消息是否丢失
systemctl restart rabbitmq-server
rabbitmqctl list_queues name messages
15.8 消息堆积排查
# 查看堆积队列
rabbitmqctl list_queues name messages messages_ready messages_unacknowledged consumers | \
awk '$2 > 1000'
# 查看消费者数量
rabbitmqctl list_queues name consumers | awk '$2 == 0'
# 查看队列的进出速率(通过管理 API)
curl -u admin:admin123 http://localhost:15672/api/queues/%2F/queue_name | \
jq '{messages, message_stats: {publish_details: {rate}, deliver_details: {rate}}}'
消息堆积解决方案
| 方案 | 说明 |
|---|---|
| 增加消费者 | 最直接的方式 |
| 提高消费并发 | 多线程/多进程消费者 |
| 增大预取值 | 减少确认等待时间 |
| 临时降级 | 丢弃低优先级消息 |
| 紧急消费 | 启动临时消费者快速消费 |
| 检查消费者异常 | 消费者是否崩溃或阻塞 |
15.9 队列故障排查
队列不可用
# 检查队列状态
rabbitmqctl list_queues name state
# 仲裁队列状态
rabbitmq-queues quorum_status "queue_name"
# 检查 Leader 是否存在
rabbitmq-queues members "queue_name"
队列参数错误
# 查看队列参数
rabbitmqctl list_queues name arguments
# 删除并重建队列(谨慎)
rabbitmqctl delete_queue queue_name
# 然后通过代码重新声明
15.10 性能问题排查
# 查看 Erlang 进程数
rabbitmqctl status | grep proc_used
# 查看文件描述符
rabbitmqctl status | grep fd_used
# 查看网络统计
rabbitmqctl list_connections name recv_oct send_oct
# 查看慢队列(消息多但消费者少)
rabbitmqctl list_queues name messages consumers | \
awk '$2 > 1000 && $3 < 2'
# 启用 Top 插件查看进程资源使用
rabbitmq-plugins enable rabbitmq_top
# 管理界面 -> Admin -> Top
15.11 常见错误代码
| 错误代码 | 含义 | 解决方案 |
|---|---|---|
PRECONDITION_FAILED | 参数不匹配 | 使用一致的参数重新声明 |
NOT_FOUND | 队列/交换机不存在 | 先声明再操作 |
RESOURCE_LOCKED | 排他队列被占用 | 使用非排他队列 |
ACCESS_REFUSED | 权限不足 | 检查用户权限 |
CONNECTION_FORCED | 连接被强制关闭 | 检查心跳和网络 |
CHANNEL_ERROR | 通道异常 | 重新创建通道 |
INTERNAL_ERROR | 内部错误 | 查看日志详情 |
15.12 故障排查检查清单
| 序号 | 检查项 | 命令/方法 |
|---|---|---|
| 1 | 服务是否运行 | rabbitmqctl status |
| 2 | 端口是否监听 | ss -tlnp | grep 5672 |
| 3 | 日志有无错误 | grep -i error /var/log/rabbitmq/*.log |
| 4 | 内存是否超限 | rabbitmqctl status | grep mem |
| 5 | 磁盘是否超限 | rabbitmqctl status | grep disk |
| 6 | 有无系统告警 | rabbitmqctl status | grep alarms |
| 7 | 集群是否健康 | rabbitmqctl cluster_status |
| 8 | 网络分区检查 | cluster_status | grep partitions |
| 9 | 连接数是否正常 | rabbitmqctl list_connections | wc -l |
| 10 | 队列是否有堆积 | rabbitmqctl list_queues messages |
15.13 扩展阅读
下一章: 第 16 章:最佳实践 — 总结生产环境的最佳实践、容量规划和运维 SOP。