laravel任务超时需协同调整三层:任务类$timeout(如30秒)、队列监听器--timeout(如60秒)、驱动retry_after(至少等于--timeout,推荐75–90秒),三者须满足$timeout<--timeout≤retry_after,否则导致提前终止或重复执行。

任务超时失败,核心是时间控制失当或配置层级不匹配。Laravel 的超时机制分三层:任务自身、队列监听器、驱动配置,必须协同调整才有效。
任务类内设置 $timeout
这是最细粒度的控制,适用于单个任务有明确执行上限的场景(如调用外部 API 不能超过 30 秒):
- 在 Job 类中定义 protected $timeout = 30;(单位:秒)
- 该值必须小于队列监听器的
--timeout值,否则会被监听器提前终止,任务无法触发自身的超时逻辑 - 若任务含循环或阻塞 I/O,建议预留 2–3 秒缓冲,避免因系统负载波动误判超时
启动监听器时指定 --timeout
这是生产环境最常用、最可控的方式,影响所有被该进程消费的任务:
- 运行命令:php artisan queue:work --timeout=60
- 该值应比绝大多数任务的预期耗时高 10–20%,但不宜超过 90 秒(尤其使用 Redis 驱动时,需配合
retry_after) - 搭配
--sleep=3可提升延迟任务的响应精度,避免空闲轮询过长导致超时判定滞后
队列驱动配置中的 retry_after
这是底层持久化层的关键参数,决定任务“被认为失败”的时间点,**必须与监听器超时对齐**:
- 在
config/queue.php的对应连接中设置:'retry_after' => 90 - 该值必须大于等于监听器的
--timeout(例如 --timeout=60 → retry_after 至少设为 60,推荐 75–90) - 若
retry_after小于--timeout,任务可能在执行中途就被驱动强制标记为失败并重试,造成重复执行
检查与验证要点
调参后务必验证是否生效:
- 查看数据库
jobs表中任务的 available_at 和 reserved_at 字段变化,确认任务是否被正常拾取和锁定 - 在任务中临时加入
Log::info('start: '.now());和Log::info('end: '.now());,比对日志时间差与设置超时值 - 用
php artisan queue:failed检查失败任务记录,若频繁出现 “The job has been reserved for too long” 提示,说明retry_after过小











