现象
队列深度持续增长但仍有消费者;messages_ready 很高,messages_unacknowledged 也不断上升;内存或磁盘告警触发后发布端阻塞、连接卡住;队列中消息年龄超过业务允许的延迟。
诊断
先区分“待投递”和“已投递未确认”:
rabbitmqctl list_queues name messages messages_ready \
messages_unacknowledged consumers consumer_utilisation
messages_ready 高且消费者利用率接近 1,说明消费能力饱和;未确认数高而消费者很少,说明消息被取走却卡在处理中;消费者为 0 则是根本没有绑定。再检查 broker 告警:
rabbitmq-diagnostics check_alarms
rabbitmqctl status | grep -A4 -E 'memory|disk_free'
内存或磁盘告警会让发布者阻塞,看起来像生产者挂了,实际是队列水位触发保护。用 rabbitmqctl list_consumers queue_name channel_pid prefetch_count active ack_required 查看预取设置,prefetch_count 为 0 表示不限制投递,单个消费者可能囤积大量消息。最后对比 message_stats.publish、ack、redeliver:重投递接近发布量说明存在 requeue 循环或消费者频繁断开。
修复
提高消费者数量或单条处理吞吐;设置 20 到 50 的有界 prefetch_count;业务处理成功后再 ack。对反复失败的消息使用 basic_nack 且 requeue=false 并配置死信交换机,避免同一消息无限循环;需要持久性时使用 quorum queue,并开启 publisher confirm 让生产端感知背压。不要仅靠提高内存水位掩盖消费瓶颈。
验证
观察一个完整流量周期:messages_ready 应停止增长或开始下降,消息年龄回到 SLA 以内,ack 速率跟上 publish 速率,redeliver 不再同步上涨。再重启一个消费者,确认不会出现新的积压尖峰,说明未确认窗口已经受控,且没有告警处于激活状态。