Supervisor 显示 consumer 是 RUNNING,RabbitMQ 队列里的 Ready 消息却一直上涨。RUNNING 只表示进程没退出,不表示它正在消费正确队列,也不表示消息处理能完成。
先确认这个进程监听的是哪一个consumer
ps -ef | grep '[q]ueue:consumers:start'
bin/magento queue:consumers:list
supervisorctl status
对照 Supervisor 配置里的 consumer 名称、Magento 配置和 RabbitMQ 实际队列绑定。配置改过但旧进程没重启时,它仍可能运行旧 consumer 或旧 release。多套环境共用 RabbitMQ vhost,也可能看错队列。
在RabbitMQ里分开看Ready和Unacked
Ready 高、Unacked 为 0,通常是没有消费者真正订阅;Unacked 持续很高,说明消息已取走但处理没完成或没有 ack。结合 connection、channel、consumer tag 和 hostname,确认是哪台机器占着消息。
如果 Ready 在下降但业务完全没有结果,别只看队列曲线,继续查消息是不是被路由到错误 consumer 或失败队列。交换机、routing key 与 queue binding 任何一个不一致,都会让“有消费者、也有消息”这两个事实彼此无关。
如果只有一条消息长期 unacked,抓 consumer 的 PHP 调用栈或打开针对性日志。外部 API 没超时、数据库锁等待、图片处理卡住,都会让进程看着 alive,实际上停在同一条消息上。
Unacked 数量刚好等于 worker 数乘以 prefetch 时,通常是所有 worker 都卡在处理阶段。此时继续加进程只会拿走更多消息并占用内存,应该先找到单条消息为什么不结束。
消息反复回队列时,先保存失败原因
消费者抛异常后立即 nack/requeue,Ready 数可能几乎不变,但日志会重复同一消息。记录 message ID、topic、重试次数和异常,设置合理的重试与失败队列,避免毒消息无限占满 worker。
重启前先判断会不会重复执行
直接 kill 卡住的 consumer 会让未确认消息重新投递。如果处理过程已经调用外部系统,只是 ack 前卡住,重投可能产生重复订单、重复邮件或重复库存动作。业务处理必须使用稳定键做幂等。
修复后观察 Ready、Unacked 和 ack rate,而不是只看 Supervisor 变绿。再投一条可识别的测试消息,确认正确 consumer 在预期时间处理,并完成一次滚动重启测试。这样才能证明进程管理和消费链路都正常。
最后把 Supervisor 的退出码、启动目录、PHP 路径和最大消息数写清楚。发布后主动滚动重启长期 consumer,确保它们加载的是新 release;否则 Web 已经运行新代码,队列进程还在执行旧类,问题会表现得非常随机。

