故障排查
本章介绍 RabbitMQ 常见问题的诊断和解决方法。
🎯 本章目标
- 掌握常见问题的诊断方法
- 学会使用诊断工具
- 了解问题解决的最佳实践
🔍 诊断命令
健康检查
# 快速健康检查
rabbitmq-diagnostics ping
# 完整健康检查
rabbitmq-diagnostics check_running
rabbitmq-diagnostics check_local_alarms
rabbitmq-diagnostics check_port_connectivity
# 所有检查
rabbitmq-diagnostics check_virtual_hosts
状态检查
# 节点状态
rabbitmqctl status
# 集群状态
rabbitmqctl cluster_status
# 环境信息
rabbitmqctl environment
资源检查
# 内存使用
rabbitmqctl status | grep -A 20 memory
# 文件描述符
rabbitmqctl status | grep file_descriptors
# 磁盘使用
rabbitmqctl status | grep disk
❌ 常见问题
1. 连接失败
问题表现
Connection refused
Connection reset
Socket closed
诊断步骤
# 1. 检查服务状态
systemctl status rabbitmq-server
# 2. 检查端口监听
netstat -tlnp | grep 5672
# 或
ss -tlnp | grep 5672
# 3. 检查防火墙
iptables -L -n | grep 5672
firewall-cmd --list-ports
# 4. 检查日志
tail -100 /var/log/rabbitmq/rabbit@hostname.log
# 5. 测试连接
telnet localhost 5672
解决方案
# 服务未启动
systemctl start rabbitmq-server
# 端口被防火墙阻止
firewall-cmd --permanent --add-port=5672/tcp
firewall-cmd --reload
# 监听地址问题
# 检查 rabbitmq.conf
# listeners.tcp.default = 0.0.0.0:5672
2. 认证失败
问题表现
ACCESS_REFUSED - Login was refused
Authentication failed
诊断步骤
# 1. 检查用户是否存在
rabbitmqctl list_users
# 2. 检查用户权限
rabbitmqctl list_user_permissions <username>
# 3. 检查虚拟主机
rabbitmqctl list_vhosts
解决方案
# 用户不存在
rabbitmqctl add_user myuser mypassword
rabbitmqctl set_permissions -p / myuser ".*" ".*" ".*"
# 密码错误
rabbitmqctl change_password myuser newpassword
# guest 用户远程访问
# 默认 guest 只能本地访问,需要创建新用户
3. 内存告警
问题表现
memory alarm triggered
publishers blocked
诊断步骤
# 1. 检查内存使用
rabbitmqctl status | grep -A 10 memory
# 2. 检查队列内存
rabbitmqctl list_queues name messages memory
# 3. 查看告警状态
rabbitmqctl list_local_alarms
解决方案
# 临时清理队列
rabbitmqctl purge_queue <queue_name>
# 调整内存阈值(rabbitmq.conf)
# vm_memory_high_watermark.relative = 0.6
# 启用惰性队列减少内存使用
rabbitmqctl set_policy lazy-queues ".*" \
'{"queue-mode":"lazy"}' --apply-to queues
4. 磁盘告警
问题表现
disk alarm triggered
publishers blocked
诊断步骤
# 1. 检查磁盘使用
df -h /var/lib/rabbitmq
# 2. 检查磁盘阈值配置
rabbitmqctl environment | grep disk_free_limit
# 3. 查看大文件
du -sh /var/lib/rabbitmq/mnesia/*
解决方案
# 清理日志
> /var/log/rabbitmq/rabbit@hostname.log
# 清理旧数据
rabbitmqctl force_gc
# 调整磁盘阈值(rabbitmq.conf)
# disk_free_limit.absolute = 1GB
# 迁移数据目录
# 1. 停止 RabbitMQ
# 2. 移动 /var/lib/rabbitmq 到大磁盘
# 3. 创建软链接
5. 消息堆积
问题表现
队列消息持续增长
消费者处理不过来
诊断步骤
# 1. 查看队列消息数
rabbitmqctl list_queues name messages messages_ready messages_unacknowledged
# 2. 查看消费者数量
rabbitmqctl list_queues name consumers
# 3. 查看消费速率
rabbitmqctl list_queues name message_stats.deliver_get.rate
# 4. 查看消费者状态
rabbitmqctl list_consumers
解决方案
// 增加消费者并发
@RabbitListener(queues = "my.queue", concurrency = "5-10")
public void handle(String message) {
// 处理消息
}
# 配置预取数量
spring:
rabbitmq:
listener:
simple:
prefetch: 50
concurrency: 5
max-concurrency: 10
6. 消息丢失
诊断步骤
# 1. 检查队列持久化
rabbitmqctl list_queues name durable
# 2. 检查消息确认
rabbitmqctl list_queues name messages_unacknowledged
# 3. 检查死信队列
rabbitmqctl list_queues name arguments | grep dead-letter
解决方案
// 1. 确保队列持久化
@Bean
public Queue durableQueue() {
return QueueBuilder.durable("my.queue").build();
}
// 2. 确保消息持久化
rabbitTemplate.convertAndSend(exchange, routingKey, message, msg -> {
msg.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);
return msg;
});
// 3. 启用发布确认
spring.rabbitmq.publisher-confirm-type=correlated
spring.rabbitmq.publisher-returns=true
// 4. 手动消费确认
spring.rabbitmq.listener.simple.acknowledge-mode=manual
7. 节点无法加入集群
问题表现
Error: unable to perform an operation on node
{:timeout, 60000}
诊断步骤
# 1. 检查 Erlang Cookie
cat /var/lib/rabbitmq/.erlang.cookie
# 2. 检查主机名解析
ping rabbitmq-node1
cat /etc/hosts
# 3. 检查防火墙
# 需要开放 4369, 25672 端口
netstat -tlnp | grep 4369
netstat -tlnp | grep 25672
解决方案
# 1. 同步 Erlang Cookie
scp /var/lib/rabbitmq/.erlang.cookie root@node2:/var/lib/rabbitmq/
chmod 400 /var/lib/rabbitmq/.erlang.cookie
# 2. 配置 hosts
echo "192.168.1.101 rabbitmq-node1" >> /etc/hosts
echo "192.168.1.102 rabbitmq-node2" >> /etc/hosts
# 3. 开放端口
firewall-cmd --permanent --add-port=4369/tcp
firewall-cmd --permanent --add-port=25672/tcp
firewall-cmd --reload
# 4. 重置并加入集群
rabbitmqctl stop_app
rabbitmqctl reset
rabbitmqctl join_cluster rabbit@rabbitmq-node1
rabbitmqctl start_app
🔧 诊断工具
rabbitmq-diagnostics
# 完整诊断报告
rabbitmq-diagnostics status
# 网络检查
rabbitmq-diagnostics check_port_connectivity
# TLS 检查
rabbitmq-diagnostics cipher_suites
# 证书检查
rabbitmq-diagnostics check_certificate_expiration
日志分析
# 查看错误日志
grep -i error /var/log/rabbitmq/rabbit@hostname.log
# 查看警告
grep -i warning /var/log/rabbitmq/rabbit@hostname.log
# 实时监控日志
tail -f /var/log/rabbitmq/rabbit@hostname.log
# 启用详细日志(rabbitmq.conf)
# log.file.level = debug
管理 API
# 节点健康
curl -u admin:password http://localhost:15672/api/healthchecks/node
# 队列详情
curl -u admin:password http://localhost:15672/api/queues/%2f/my.queue
# 连接详情
curl -u admin:password http://localhost:15672/api/connections
📊 性能诊断
吞吐量分析
# 查看消息速率
rabbitmqctl list_queues name message_stats.publish.rate message_stats.deliver_get.rate
# 查看连接吞吐
rabbitmqctl list_connections name recv_oct_details.rate send_oct_details.rate
延迟分析
@Slf4j
@Component
public class LatencyMonitor {
@RabbitListener(queues = "monitor.queue")
public void checkLatency(Message message) {
Long publishTime = (Long) message.getMessageProperties()
.getHeaders().get("publish_time");
if (publishTime != null) {
long latency = System.currentTimeMillis() - publishTime;
if (latency > 1000) {
log.warn("⚠️ 高延迟: {}ms", latency);
}
}
}
}
📝 本章小结
常见问题速查表
| 问题 | 关键诊断命令 | 常见原因 |
|---|---|---|
| 连接失败 | netstat -tlnp | 服务未启动/防火墙 |
| 认证失败 | rabbitmqctl list_users | 用户/密码错误 |
| 内存告警 | rabbitmqctl status | 消息堆积 |
| 磁盘告警 | df -h | 磁盘空间不足 |
| 消息堆积 | rabbitmqctl list_queues | 消费者不足 |
| 集群问题 | rabbitmqctl cluster_status | Cookie/网络 |
排查流程
1. 检查服务状态
↓
2. 检查日志错误
↓
3. 检查资源使用(内存/磁盘)
↓
4. 检查网络连接
↓
5. 检查配置参数
↓
6. 必要时重启服务
下一步
掌握故障排查后,让我们学习 版本升级!
