yii2-queue 默认不自动运行任务,需显式启动监听进程或通过 cron 触发;驱动配置、组件注册、日志行为、进程管理及任务类序列化均需严格遵循规范,否则任务挂起或执行失败。

yii2-queue 默认不自动运行任务,必须显式启动监听进程或通过 Cron 触发执行,否则推入队列的任务会一直挂起。
确认你用的是哪个驱动
yii2-queue 支持多种后端:redis、db、amqp、beanstalk 等。不同驱动的配置项和行为差异很大,尤其在连接失败、重试逻辑、消息可见性上。
-
redis驱动依赖yii\redis\Connection,需确保hostname、port、database与实际 Redis 实例一致;常见错误是database写成字符串"0"而非整数0,导致连接静默失败 -
db驱动需要先运行yii migrate创建queue表,表结构不匹配(比如缺少channel字段)会导致push()报错SQLSTATE[HY000]: General error: 1364 Field 'channel' doesn't have a default value - 使用
beanstalk时,host和port必须指向beanstalkd进程,而非 Nginx 或 PHP-FPM;本地开发常用localhost:11300,但 Docker 环境中应填容器名如beanstalkd:11300
console.php 里必须正确注册 queue 组件
组件配置写错位置或类名拼错,会导致 Yii::$app->queue 为 null,调用 push() 时直接报 Call to a member function push() on null。
- 配置必须放在
config/console.php的'components'数组内,不能放在web.php里(Web 请求无法触发监听) - 类名要完整:Redis 驱动是
'class' => \yii\queue\redis\Queue::class,不是yii\queue\RedisQueue(后者不存在) - 必须设置
'as log' => \yii\queue\LogBehavior::class,否则失败任务不会记录日志,排查无从下手
任务执行靠 listen 命令,不是自动轮询
Yii 不像 Laravel Horizon 那样自带守护进程,queue/listen 是阻塞式命令,退出即停。生产环境必须配合 supervisor 或 systemd 管理,不能只靠 php yii queue/listen 手动跑。
- 推荐用
supervisor启动:命令写成php /path/to/yii queue/listen --verbose --color=1,并设autostart=true和autorestart=true - 若用 Cron 每分钟拉一次(
* * * * * php yii queue/exec --verbose),注意--ttr(time-to-run)参数必须大于单次任务预期耗时,否则任务可能被重复执行 -
queue/exec是单次执行模式,适合短任务;queue/listen是长连接模式,适合高吞吐,但 Redis 驱动下若网络抖动易断连,需搭配--retry参数
任务类必须可序列化且无闭包依赖
推入队列的对象会被 serialize(),任何含 $this->closure、PDO 实例、Yii::$app 引用的类都会在反序列化时报 Serialization of 'Closure' is not allowed 或 Uncaught Error: __PHP_Incomplete_Class。
- 任务类应继承
\yii\queue\JobInterface,实现execute($queue)方法,内部只用传入参数和静态方法 - 不要在构造函数里初始化数据库连接或依赖注入容器;改用
execute()中按需获取Yii::$app->db - 如果用了
gii生成的任务类,检查是否意外引入了use app\controllers\SiteController这类控制器引用——控制器不可序列化
最容易被忽略的是:Redis 驱动下,queue/listen 进程启动后不会自动重连失效连接,一旦 Redis 重启,该进程就卡死不动,必须由进程管理器检测并重启。别只盯着任务逻辑,先保底让监听活着。











