直接选 yii\queue\amqp_interop\Queue——它是Yii2官方推荐、维护活跃、兼容PHP 8+和RabbitMQ 3.10+的AMQP驱动,旧版yii\queue\amqp\Queue已停更且依赖过时库,易在TLS、vhost或SASL认证上失败。
用
还是
?
直接选
——这是 Yii2 官方推荐、维护更活跃、兼容 PHP 8+ 和 RabbitMQ 3.10+ 的 AMQP 驱动。旧版
已基本停更,且依赖过时的
,容易在 TLS 连接、vhost 路径或 SASL 认证上失败。
常见错误现象:
或
,往往是因为驱动底层协议栈不匹配。
必须用
+
(注意不是
)
是纯 PHP 实现,不依赖
扩展,部署更轻量
若你已装了
,反而要禁用它,否则可能触发冲突(如
)
必须加,但只对 console 有效
这个配置让队列组件在控制台应用启动时自动注册监听器,否则
命令根本不会响应任何任务 —— Web 请求里加它没用,也别加。
使用场景:只有在
里配才生效;
中配置只会浪费内存,且可能引发
类错误。
要放在
的
同级位置
确保
存在(
yii
2-queue 自带),否则
命令无法识别
如果用 Supervisor 管理消费者进程,命令必须是
,不能漏掉
,否则失败时不报错也不退出
和
不是“重试次数”,而是“单次最长执行时间 + 全局失败阈值”
很多人以为
表示失败后立刻重试 2 次,其实不是:它表示该任务最多被投递 3 次(含首次),每次失败后默认延迟约 1 秒再入队 —— 这个行为由驱动内部实现,不可配置间隔。
更关键的是
(Time To Run):它限制的是单次
方法执行的**最大耗时**,超时会强制终止进程并标记为失败,然后计入
计数。若任务本身需要 6 分钟处理,却设
(5 分钟),就会被粗暴 kill,且无法恢复上下文。
单位是秒,建议设为实际业务逻辑平均耗时的 1.5–2 倍,但不要超过 RabbitMQ 的
(默认 60s),否则连接可能被服务端断开
设为 1 表示“只试一次,失败即丢弃”,适合日志类、通知类等幂等性弱的任务
真正需要可靠重试的场景(如支付回调),应配合死信队列(DLX)+ 延迟插件,而不是靠
硬扛
消息体序列化默认用
,但你大概率要用
yii2-queue 默认用
序列化任务对象,速度快、体积小,但有个致命问题:它把类名和属性名一起编码,一旦你改了 Job 类名或字段名,所有未消费的老任务都会反序列化失败,报
。
真实项目里,Job 类频繁迭代、团队协作多、上线节奏快 —— 此时 JSON 是更安全的选择,哪怕慢一点、大一点,也比批量卡死强。
在 queue 组件配置中加
JSON 序列化要求 Job 类所有 public 属性可 JSON 化(不能含 resource、Closure、PDO 实例等)
若 Job 构造函数参数较多,建议用数组传参(
),而非裸对象传参,避免反序列化歧义
最常被忽略的一点:RabbitMQ 的
不是“随便起个名字就行”。它本质是 AMQP 的 queue name,受服务端字符限制(如不能含
、空格、控制字符),且大小写敏感;如果多个环境共用一个 RabbitMQ 实例,务必在名称里带上环境前缀,比如
,否则开发机一跑
,就把线上队列里的任务全抢走了。
yii\queue\amqp_interop\Queueyii\queue\amqp\Queueyii\queue\amqp_interop\Queueyii\queue\amqp\Queueenqueue/amqp-libConnection refusedAMQP protocol error: FRAME_END missingcomposer require yiisoft/yii2-queuecomposer require enqueue/amqp-libphp-amqplibenqueue/amqp-libamqp.soamqp.soClass 'AMQPConnection' not found'bootstrap' => ['queue']yii queue/listenconsole/config/main.phpweb/config/main.phpCannot use object of type yii\queue\amqp_interop\Queue as array'bootstrap' => ['queue']console/config/main.php'components'console/controllers/QueueController.phpyii queue/listenphp yii queue/listen --verbose--verbosettrattemptsattempts => 3ttrexecute()attemptsttr => 300ttrheartbeatattemptsattemptsigbinaryjsonigbinaryunserialize(): Error at offset'serializer' => \yii\queue\serializers\JsonSerializer::classnew SendEmailJob(['to' => 'a@b.c', 'template' => 'welcome'])queueName/prod_send_emailyii queue/listen