Yii2队列任务不执行的根源是worker未真正拉取任务,主因包括CLI配置错位、驱动未就绪或进程静默退出;需验证console配置、驱动连接、表结构、序列化兼容性及channel隔离。

Yii2.0项目部署后队列任务始终不执行,不是代码没写、也不是任务没推,而是worker进程根本没真正拉取到任务——常见于配置错位、驱动未就绪或进程被 silently kill。
确认worker是否真在运行
执行ps -ef | grep -v grep | grep queue/listen或ps aux | grep queue/run,只看到一条匹配行不等于进程正常:它可能刚启动就因配置错误退出,且无日志输出。
加--verbose参数重试一次:php yii queue/listen --verbose,观察终端是否立即退出;若3秒内退出且无任何输出,说明驱动初始化失败,不是“没任务”,而是“连队列都连不上”。
【关键前提】 CLI 环境必须加载console/config/main.php中的队列配置,web.php里的配置对worker完全无效。
检查Redis或DB驱动是否可用
方法一:手动测试Redis连接
在console应用中运行:php yii serve/test-redis(需自定义命令),或直接执行:php -r "var_dump((new \Predis\Client(['scheme'=>'tcp','host'=>'127.0.0.1','port'=>6379]))->ping());"。返回string(4) "PONG"才算通。
方法二:验证DB驱动表结构
若用yii\queue\db\Queue,先确认已执行php yii queue/migrate,再查数据库是否存在queue表(或你自定义的table_name),且字段job类型为TEXT而非VARCHAR(255)——后者会导致长任务序列化内容被截断,反序列化静默失败。
方法三:抓取驱动报错
临时在console/config/main.php的components里给queue加'as log' => \yii\queue\LogBehavior::class,再跑queue/listen,错误会打到runtime/logs/app.log里。没这行,90%的驱动初始化异常都看不到。
验证任务是否真正入队
第一步:用最简任务测试
在任意控制器中写:\Yii::$app->queue->push(new \app\jobs\PingJob());,该类只含一个空execute()方法。
第二步:直查存储介质
Redis用户执行:redis-cli LLEN queue,返回数字>0说明入队成功;DB用户查SELECT COUNT(*) FROM queue WHERE status = 0;,结果应为1。
第三步:确认channel隔离
多个商城共用Redis时,'channel' => 'zjhj_bd_735'必须全局唯一。若A项目用default,B项目也用default,B的worker会把A的任务抢走并执行失败——因为任务类路径在B项目里不存在,反序列化直接抛Class not found,但状态卡在reserved,面板里也看不见。
排查worker卡住或秒退的底层原因
① 检查MySQL wait_timeout
运行mysql -e "SHOW VARIABLES LIKE 'wait_timeout';",若值≤60,而你的ttr设为300,worker在执行第2个任务时数据库连接已断,后续所有任务因PDOException: MySQL server has gone away全部失败。解决方案:在console/config/main.php的db组件里加'attributes' => [PDO::ATTR_TIMEOUT => 10],并设'wait_timeout' => 28800(8小时)。
② 验证Redis连接超时设置
Redis驱动默认不设timeout,网络抖动时BRPOP阻塞调用直接超时退出。必须显式配置:'redis' => ['class' => 'yii\redis\Connection', 'hostname' => '127.0.0.1', 'port' => 6379, 'timeout' => 10],,并在queue配置中引用该redis组件。
③ 查看PHP扩展是否缺失
Redis驱动要求predis/predis或phpredis扩展二选一。只装predis包但没启用ext-redis,或反过来,都会报Unknown driver "redis"。执行php -m | grep redis确认CLI模式下扩展已加载。
确认任务类能否被正确反序列化
任务类构造函数里禁止传$this->db、Yii::$app或闭包——这些无法序列化,反序列化时直接Fatal error导致worker崩溃。必须改用ID查库:public function __construct(public int $orderId) {},在execute()里再$order = Order::findOne($this->orderId);。
【易错点】 handle()方法签名不能带类型声明:public function handle(Job $job)在PHP 7.4+会因反序列化失败静默跳过,必须写成public function handle()。
检查任务类是否被composer自动加载:执行php composer.phar dump-autoload --optimize,尤其部署后文件权限变更或Git忽略vendor/autoload.php时,autoload失效会导致Class not found。


















