首页 > 解决方案 > 如何防止 Laravel 6.x 队列调度程序多次尝试相同的作业 ID?

问题描述

我注意到 Laravel 正在创建相同 ID 的重复作业,例如在下面的列表中,您可以看到作业 ID 306 被尝试了两次(以及 296,298,305)

[2021-03-12 20:28:04][296] Processing: App\Jobs\RunImport
[2021-03-12 20:28:04][297] Processing: App\Jobs\RunImport
[2021-03-12 20:28:04][298] Processing: App\Jobs\RunImport
[2021-03-12 20:28:04][299] Processing: App\Jobs\RunImport
[2021-03-12 20:28:23][297] Processed:  App\Jobs\RunImport
[2021-03-12 20:28:23][300] Processing: App\Jobs\RunImport
[2021-03-12 20:28:39][301] Processing: App\Jobs\RunImport
[2021-03-12 20:28:57][301] Processed:  App\Jobs\RunImport
[2021-03-12 20:28:57][302] Processing: App\Jobs\RunImport
[2021-03-12 20:29:15][299] Processed:  App\Jobs\RunImport
[2021-03-12 20:29:15][303] Processing: App\Jobs\RunImport
[2021-03-12 20:29:35][300] Processed:  App\Jobs\RunImport
[2021-03-12 20:29:35][296] Processing: App\Jobs\RunImport
[2021-03-12 20:29:36][296] Failed:     App\Jobs\RunImport
[2021-03-12 20:29:36][298] Processing: App\Jobs\RunImport
[2021-03-12 20:29:36][298] Failed:     App\Jobs\RunImport
[2021-03-12 20:29:36][304] Processing: App\Jobs\RunImport
[2021-03-12 20:29:44][304] Processed:  App\Jobs\RunImport
[2021-03-12 20:29:44][305] Processing: App\Jobs\RunImport
[2021-03-12 20:30:05][302] Processed:  App\Jobs\RunImport
[2021-03-12 20:30:05][306] Processing: App\Jobs\RunImport
[2021-03-12 20:32:12][303] Processed:  App\Jobs\RunImport
[2021-03-12 20:32:12][305] Processing: App\Jobs\RunImport
[2021-03-12 20:32:13][305] Failed:     App\Jobs\RunImport
[2021-03-12 20:32:13][306] Processing: App\Jobs\RunImport
[2021-03-12 20:32:13][306] Failed:     App\Jobs\RunImport
[2021-03-12 20:32:13][307] Processing: App\Jobs\RunImport
[2021-03-12 20:32:43][305] Processed:  App\Jobs\RunImport
[2021-03-12 20:32:43][308] Processing: App\Jobs\RunImport
[2021-03-12 20:32:46][308] Processed:  App\Jobs\RunImport
[2021-03-12 20:32:46][309] Processing: App\Jobs\RunImport
[2021-03-12 20:32:50][309] Processed:  App\Jobs\RunImport
[2021-03-12 20:32:50][310] Processing: App\Jobs\RunImport
[2021-03-12 20:33:05][306] Processed:  App\Jobs\RunImport
[2021-03-12 20:33:09][307] Processed:  App\Jobs\RunImport
[2021-03-12 20:33:30][310] Processed:  App\Jobs\RunImport

此日志取自发送给主管的输出

[program:laravel-import]
process_name=%(program_name)s_%(process_num)02d
command=php /home/myapp/myapp-console/current/artisan queue:work --queue=import --tries=1 --timeout=21600 -vvv
autostart=true
autorestart=true
user=myapp
numprocs=4
redirect_stderr=true
stdout_logfile=/home/myapp/myapp-console/current/storage/logs/worker-import.log
stopwaitsecs=3600

我有以下时间表Kernel.php。数据源是客户端特定的端点,他们可以在其中设置计划以运行导入

protected function schedule(Schedule $schedule) {
  // start jobs on import queue from user defined schedule
  $datasources = Datasource::all();
  foreach ($datasources as $datasource) {
    if (!empty($datasource->schedule) && $datasource->company->active) {
      $schedule->call(function() use ($datasource) {
        Log::channel('import-runtime')->info("Creating new import for {$datasource->datasource_key}");
        $datasource->createImport();
      })->name("datasource-{$datasource->id}")->withoutOverlapping()->cron($datasource->schedule)->runInBackground();
    }
  }
}

createImport()函数将作业添加到工作队列

public function createImport($onDemand = false) {
  $import = new Import();
  $import->datasource_id = $this->id;
  $import->status = 'awaiting';
  $import->start_at = Carbon::now();
  $import->save();
  $queue = $onDemand ? 'import-ondemand' : 'import';
  Log::channel('import-runtime')->info("[ds_{$import->datasource_id}_import_{$import->id}] Import created, adding to queue {$queue}");
  RunImport::dispatch($import)->onQueue($queue);
}

我将每个人的日程安排都设置为相同的 cron 格式'28 20 * * *',并让工作人员完成所有工作。然后我得到错误Illuminate\Queue\MaxAttemptsExceededException

如何防止这些工作被多次尝试?

标签: phplaravel

解决方案


更改为 redis 并没有解决这个问题,同样的重复。但是我找到了根本原因。看起来队列上的设置与内部--timeout=无关retry_afterconfig/queue.php

如果您有长时间运行的作业,您必须同时--timeout和设置retry_after为您预期的最大持续时间。

我继续queue.php为长时间运行的进程创建了另一个连接,然后在主管中确保它使用了那个长时间运行的队列,而不是使用默认值 90 秒的标准队列


推荐阅读