队列任务静默消失主因是QUEUE_CONNECTION配为sync驱动,应改为redis等异步驱动并清配置缓存;闭包序列化失败需传ID而非Request或闭包;failed()未触发多因接口缺失或Horizon覆盖;积压卡死需查Redis/DB连接及Supervisor重启配置。

队列任务直接消失,连失败日志都没有
这是最让人抓狂的情况:任务 dispatch() 了,但 php artisan queue:work 根本没处理,也没报错。大概率是队列驱动配错了——Laravel 默认用 sync 驱动,它不走后台进程,而是同步执行,出错就直接抛异常;一旦你没捕获,任务就“静默失败”。
- 检查
.env中的QUEUE_CONNECTION是否设为redis、database或beanstalkd,不是sync - 运行
php artisan config:clear,避免缓存旧配置 - 用
php artisan queue:work --verbose启动,看第一行是否显示实际连接的驱动名(比如 “Processing jobs from redis…”) -
sync只适合本地开发调试,上线必须换掉
任务报 Serialization of closure is not allowed
这个错误几乎都发生在你往队列里传了匿名函数、闭包或未序列化的对象(比如 Request 实例、Eloquent 模型未加 protected $casts 或未实现 __serialize)。Laravel 队列靠序列化把任务存到 Redis/DB,闭包不能被序列化。
- 别在
dispatch()时传function() {}、fn() =>或$request - 需要请求数据?只传 ID 或必要字段,进任务后再查库:
SomeJob::dispatch($user->id) - 模型要可序列化:确保模型没引用不可序列化的属性(如
App\Http\Controllers\Controller实例),且 Laravel 版本 ≥ 9.2 会自动处理模型序列化,但低版本需手动->toArray()或用serializeDate()
重试 3 次后进 failed_jobs 表,但没触发 failed() 方法
任务进了失败表,但你在 Job 类里写的 failed() 方法没执行,说明 Laravel 根本没调用它——常见原因是 Job 类没正确实现 ShouldBeUnique 或 InteractsWithQueue 接口,或者用了自定义的失败处理逻辑覆盖了默认流程。
- 确认 Job 类里有
public function failed(\Exception $exception)方法,且没有try/catch吞掉所有异常 - 检查是否启用了
--tries=1或retryAfter设为 0,导致没机会重试就进失败表 - 如果用了 Horizon,它的失败监听优先级高于 Laravel 原生逻辑,得去 Horizon 配置里开
failed事件回调,否则failed()不生效 - 数据库驱动下,
failed_jobs表必须存在且可写,否则失败任务直接丢弃
监控不到队列积压,php artisan queue:work 却卡死不动
表面看进程活着,但新任务一直不消费,queue:work 日志停在某条之后。这通常不是代码问题,而是底层连接或资源卡住:Redis 连接超时、数据库连接池耗尽、或是 Supervisor 配置里没设 autorestart=true,导致 worker 因内存溢出或 SIGTERM 挂了却没重启。
- 别只看进程是否存在,用
redis-cli llen queues:default(Redis)或SELECT COUNT(*) FROM jobs;(DB)确认队列里真有任务 - 给
queue:work加--max-jobs=100 --max-time=3600,强制轮转,防止单个 worker 跑太久内存泄漏 - Supervisor 的
stdout_logfile和stderr_logfile必须可写,否则错误全丢进黑洞 - PHP OPcache 开启时,某些修改不会热更新,改完 Job 类记得
php artisan opcache:clear
队列真正难的不是写 Job 类,而是让连接稳、序列化安全、失败可追溯。这三个点漏一个,排查时间就翻倍。











