本文目录导读:

在 Laravel 中配置队列任务的重试次数和间隔,主要有以下几种方式:
在任务类中定义
通过属性定义
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* 任务最大尝试次数
*
* @var int
*/
public $tries = 3;
/**
* 任务重试前延迟的秒数
*
* @var int
*/
public $backoff = 60; // Laravel 8.x 及以上
// 或者使用数组定义不同的延迟时间
// public $backoff = [10, 30, 60]; // 第1次重试延迟10秒,第2次延迟30秒,第3次延迟60秒
/**
* 执行任务
*
* @return void
*/
public function handle()
{
// 任务逻辑
}
}
Laravel 8.x 以下版本使用 retryAfter
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class SendEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/**
* 任务最大尝试次数
*
* @var int
*/
public $tries = 3;
/**
* 任务重试前的延迟(秒) - Laravel 7.x 及以下
*
* @var int
*/
public $retryAfter = 60;
public function handle()
{
// 任务逻辑
}
}
在队列配置文件或运行时设置
通过 .env 文件配置
# 队列连接配置 QUEUE_CONNECTION=redis # 队列进程配置 (supervisor 配置中) QUEUE_WORKER_TRIES=3 QUEUE_WORKER_TIMEOUT=60 QUEUE_WORKER_SLEEP=3 QUEUE_WORKER_BACKOFF=30 QUEUE_WORKER_MAX_TIME=3600
运行时通过命令行参数
# 指定尝试次数 php artisan queue:work --tries=3 # 指定超时时间 php artisan queue:work --timeout=60 # 指定重试延迟 php artisan queue:work --backoff=30 # 组合使用 php artisan queue:work redis --tries=3 --timeout=60 --backoff=30
通过排队任务时动态设置
<?php
namespace App\Http\Controllers;
use App\Jobs\SendEmailJob;
use Illuminate\Http\Request;
class EmailController extends Controller
{
public function send()
{
// 创建任务时设置尝试次数和延迟
$job = new SendEmailJob();
// 动态设置尝试次数
$job->tries = 5;
// 动态设置重试延迟
$job->backoff = [30, 60, 120, 240, 480]; // 每次重试不同的延迟
// 推送到队列
dispatch($job);
}
}
使用队列事件监听器
<?php
namespace App\Providers;
use Illuminate\Queue\Events\JobFailed;
use Illuminate\Queue\Events\JobAttempted;
use Illuminate\Support\Facades\Queue;
use Illuminate\Support\ServiceProvider;
class QueueEventServiceProvider extends ServiceProvider
{
public function boot()
{
// 监听队列任务失败
Queue::failing(function (JobFailed $event) {
// $event->job->attempts() - 当前尝试次数
// $event->exception - 异常信息
logger('队列任务失败', [
'job' => $event->job->resolveName(),
'attempts' => $event->job->attempts(),
'error' => $event->exception->getMessage(),
]);
});
// 监听队列任务执行(包括重试)
Queue::after(function (JobAttempted $event) {
// 任务尝试后的回调
});
}
}
配置示例(Supervisor)
[program:worker] process_name=%(program_name)s_%(process_num)02d command=php /path/to/project/artisan queue:work redis --tries=3 --timeout=60 --backoff=30 autostart=true autorestart=true stopasgroup=true killasgroup=true user=www-data numprocs=8 redirect_stderr=true stdout_logfile=/path/to/project/storage/logs/worker.log stopwaitsecs=3600
完整示例:带指数退避的队列任务
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
class ProcessPaymentJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
/** @var int 最大尝试次数 */
public $tries = 5;
/** @var array 重试间隔(秒)- 指数退避策略 */
public $backoff = [10, 30, 60, 180, 300];
/** @var int 超时时间(秒) */
public $timeout = 120;
/** @var bool 失败后是否删除任务 */
public $deleteWhenMissingModels = true;
public function handle()
{
try {
// 业务逻辑
$this->processPayment();
} catch (\Exception $e) {
Log::error('支付处理失败', [
'message' => $e->getMessage(),
'attempts' => $this->attempts(),
]);
// 如果还有重试次数,释放任务回去
if ($this->attempts() < $this->tries) {
$this->release($this->getNextBackoff());
} else {
throw $e; // 达到最大次数,抛出异常标记为永久失败
}
}
}
/**
* 获取下一次重试的延迟时间
*/
protected function getNextBackoff()
{
$attempts = $this->attempts();
if (is_array($this->backoff)) {
return $this->backoff[$attempts - 1] ?? $this->backoff[count($this->backoff) - 1];
}
return $this->backoff;
}
/**
* 任务最终失败的处理器
*/
public function failed(\Throwable $exception)
{
Log::error('支付处理最终失败', [
'error' => $exception->getMessage(),
]);
// 可以在这里发送通知
}
}
优雅处理重试的方法
<?php
namespace App\Jobs;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class HandleExternalApi implements ShouldQueue
{
use Dispatchable;
public $tries = 3;
public $backoff = [15, 60, 300];
public $timeout = 120;
public function handle()
{
$response = $this->callExternalApi();
if ($response->status() === 429) {
// 速率限制,释放任务并延迟重试
$this->release(300);
}
if ($response->status() !== 200) {
throw new \Exception('外部API错误');
}
// 处理成功
}
}
注意事项
- 重试次数配置位置优先级:任务属性 > 队列命令参数 > 队列配置
backoff属性:Laravel 8.x 及以上使用,替代了旧的retryAfter- 防止无限重试:确保
tries不会设置为很大的值 - 错误日志:记录每次重试的原因和时间
- 监控:使用 Laravel Horizon 或自定义监控来跟踪队列状态
这样配置后,Laravel 会自动处理队列任务的重试机制,当任务执行失败时会按照配置的时间和次数自动重试。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播