laravel 10中timeout控制单个任务最大执行时长,防止卡死占用worker;可在任务类设$timeout属性、分发时链式调用timeout()方法,或启动worker时加--timeout参数,且retry_after必须≥timeout以避免重复执行。

在 Laravel 10 中,任务超时(timeout)控制的是单个队列任务的**最大执行时长**,而非调度频率或延迟时间。它防止某个耗时过久或卡死的任务长期占用 worker 进程,影响其他任务处理。
在任务类中设置 $timeout 属性
这是最常用、最直接的方式。只需在 Job 类中定义 $timeout 属性(单位:秒):
- 该值会覆盖全局配置,对当前任务生效
- 支持整数,例如
60表示最多运行 60 秒 - 若未设置,将回退到配置文件中的默认值(
config/queue.php的'retry_after'或'timeout',具体取决于驱动)
示例:
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue;
public $timeout = 120; // 任务最多执行 120 秒
public function handle(): void
{
// 可能耗时的操作,如 FFmpeg 转码、大文件解析等
sleep(90); // 模拟耗时操作
}
}
通过链式调用动态设置 timeout
分发任务时,可使用 onConnection()、onQueue() 等方法配合 timeout() 方法(Laravel 10.40+ 支持):
-
timeout(30)表示本次分发的任务单独设定为 30 秒超时 - 优先级高于类中定义的
$timeout属性 - 适用于同一任务类在不同场景下需差异化超时控制的情况
示例:
// 该次分发强制超时为 30 秒,忽略类中 $timeout = 120
ProcessPodcast::dispatch($podcast)->timeout(30);
// 延迟 + 超时组合
SendEmailJob::dispatch($user)
->delay(now()->addMinutes(5))
->timeout(45);
注意不同队列驱动的 timeout 行为差异
Laravel 的超时机制依赖底层驱动能力,实际表现略有不同:
-
Redis 驱动:worker 会监控任务执行时间,超时后自动释放并标记失败(需配合
retry_after设置合理值) -
Database 驱动:依赖
jobs表的reserved_at和available_at字段,超时判断基于数据库轮询周期,精度略低 -
Sync 驱动:不启用异步,
$timeout不生效;仅用于本地调试,无超时保护
建议生产环境使用 Redis,并确保 retry_after ≥ $timeout,避免任务被误判为“卡死”而重复执行。
全局默认超时与重试配置
可在 config/queue.php 中统一调整:
-
'redis' => [... 'retry_after' => 90, ...]:表示任务被取出后,若 90 秒内未完成,将被视为失败并放回队列(影响重试逻辑) -
'database' => [... 'retry_after' => 90, ...]:同理,也作为数据库驱动的隐式超时依据 - 注意:
retry_after≠$timeout,但二者需协同设置——通常retry_after应略大于最大预期$timeout
例如:任务设 $timeout = 60,则 retry_after 推荐设为 75~90,留出序列化/网络开销余量。











