强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

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/rabbit@hostname.log

15.2 连接问题

问题一:连接被拒绝

症状: Connection refusedAMQPConnectionError

排查步骤:

# 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。