Illuminate\Queue\MaxAttemptsExceededException:App\Jobs\SendNotification 已尝试次数过多或运行时间过长。该作业可能已被强制终止的工作进程处理过。
Illuminate\Queue\MaxAttemptsExceededException: App\Jobs\SendNotification has been attempted too many times or run too long. The job may have been previously processed by a worker that was forcefully terminated.
ID: php/laravel-queue-worker-sigterm-timeout
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| laravel 10 | active | — | — | — |
| laravel 11 | active | — | — | — |
| php 8.2 | active | — | — | — |
| php 8.3 | active | — | — | — |
| horizon 5.21 | active | — | — | — |
根因分析
Laravel 队列工作进程在处理作业时收到 SIGTERM 信号(例如在部署或扩展期间),导致作业被标记为失败或重新尝试而未正确释放,超过了最大尝试次数限制。
English
A Laravel queue worker received a SIGTERM signal (e.g., during deployment or scaling) while processing a job, causing the job to be marked as failed or re-attempted without proper release, exceeding the maximum attempts limit.
官方文档
https://laravel.com/docs/11/queues#max-attempts解决方案
-
Implement a `failed` method in the job to handle the exception gracefully, and use `php artisan queue:retry all` to re-run failed jobs after ensuring workers are stable.
-
Add a `pcntl_signal` handler in the job's `handle` method to catch SIGTERM and release the job back to the queue: `pcntl_signal(SIGTERM, function () { $this->release(30); });`
无效尝试
常见但无效的做法:
-
Increasing the `--tries` option on the queue worker to a very high number
80% 失败
The issue is not about the number of attempts but about the job being incorrectly marked as failed due to SIGTERM; increasing tries may delay the failure but not prevent it.
-
Disabling the `force` option in deploy scripts that send SIGTERM
70% 失败
SIGTERM is necessary for graceful shutdown; disabling it can cause longer downtimes or zombie processes.