监控显示某个 Magento Consumer 每隔几分钟出现一个新 PID,运维判断为“进程不稳定”。但 --max-messages 本来就会让 Consumer 处理到指定数量后正常退出,再由 Supervisor 拉起。需要先看退出码、处理消息数和内存曲线,不能仅凭 PID 变化。

正常轮换是什么样

进程处理固定数量消息,退出码为 0,日志没有异常,Supervisor 按配置重新启动;每轮耗时随队列流量变化。这种轮换能释放长进程积累的内存。max-messages 太小会频繁启动,太大又可能让泄漏持续放大,需要按启动成本与内存稳定性选择。

bin/magento queue:consumers:start consumer.name --max-messages=500
supervisorctl status
journalctl -u supervisor --since '30 minutes ago'

命令名称与服务管理方式以当前环境为准。

OOM Kill 的证据在系统层

进程突然消失、应用没有完整异常,退出码 137 或系统日志出现 killed process,优先查容器/主机内存限制。记录 RSS 随处理消息数是否持续增长;如果每条消息后不回落,检查静态缓存、大对象数组、未释放集合和第三方 SDK。

毒消息造成固定点崩溃

每次重启后立刻处理同一消息并异常,队列长度不下降,说明某条 payload 可重复触发失败。记录 message ID、topic、重试次数和脱敏错误,把它送入失败队列或隔离后修消费者。直接删除整队列会丢掉正常业务。

数据库与 Broker 断线

长连接经过空闲超时后失效,下一条消息可能抛 connection gone away;RabbitMQ heartbeat、网络设备超时和 MySQL wait_timeout 都要对齐。消费者应能在可恢复错误后重连,但不能对已部分执行的业务无限重试,幂等键仍然必要。

一张判断表

退出码 0 且固定消息数:正常轮换;137 且内存顶格:OOM;固定 payload 重现:毒消息;随机网络异常:连接与重试;启动即退出且无消息:命令、权限或配置。修复后同时观察处理速率、队列积压、RSS 和重启原因,不能只把 Supervisor 的 restart 次数清零。

优雅停止避免重复消费

部署或扩容时给 Consumer 足够时间完成当前消息并确认 ack。强制 kill 发生在业务已写库、消息尚未确认之间时,Broker 会重新投递;消费者若没有幂等保护,就会重复发邮件、扣积分或推 ERP。测试 SIGTERM、进程超时和重启流程,确认未完成消息能安全重试。

确认 Cron 不在重复启动同一 Consumer

Magento 的 consumers runner、Supervisor、Kubernetes Deployment 可能同时管理进程。如果三处都启用,就会产生超出预期的并发和重启日志。列出每个 consumer 的唯一主管理器、期望副本数与启动参数;扩容应改这一处,而不是在多个系统分别增加进程。

同一队列提高并发前还要确认处理顺序是否有业务要求。订单状态事件若乱序消费,吞吐提高反而会制造回退。