Laravel的Job使用指南


Laravel的Job中不要有中断程序的代码,supervisord也是

在 Laravel 中,有多种方法可以中断程序执行。然而,在队列任务(Jobs)中使用这些方法时需要特别小心,因为它们可能会导致队列任务被多次执行。以下是一些常见的方法来中断程序,以及在队列任务中使用时的注意事项:

1. exit() 和 die()

这两个函数可以立即终止脚本的执行。然而,在队列任务中使用它们会导致队列处理器停止工作,从而导致任务多次执行。

1
2
exit('Terminating script');
die('Terminating script');

2. abort()

Laravel 提供的 abort() 函数可以用于中断当前请求并返回特定的 HTTP 状态码。这在控制器中非常有用,但在队列任务中不建议使用。

1
abort(403, 'Unauthorized action.');

3. 抛出异常

在队列任务中,抛出异常是中断任务执行的推荐方法。Laravel 的队列系统会捕获异常,根据配置决定是否重试任务。

1
throw new \Exception('Something went wrong');

4. return 语句

在函数或方法中使用 return 语句可以中断执行并返回控制权。这在控制器和其他方法中非常有用,但在队列任务中需要确保返回值的正确处理。

1
return;

解决队列任务多次执行的问题

为了避免队列任务被多次执行,可以使用以下方法:

  1. 确保任务是幂等的:设计任务时确保其多次执行不会产生副作用。
  2. 使用锁机制:在任务执行前获取锁,确保同一时间只有一个实例在运行。
  3. 设置重试次数:在 jobs 类中定义 public $tries = 1; 来限制任务的重试次数。

以下是一个示例,展示如何在队列任务中处理异常并使用锁机制来防止任务多次执行:

name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?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\Artisan;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Cache;

class ArtisanCommandJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

public $tries = 1;
protected $command;
protected $arguments;

public function __construct(string $command, array $arguments)
{
$this->command = $command;
$this->arguments = $arguments;
}

public function handle()
{
$lockKey = 'artisan_command_' . md5($this->command . serialize($this->arguments));
$lock = Cache::lock($lockKey, 300);

if ($lock->get()) {
try {
Log::info('Executing Artisan command', ['command' => $this->command, 'arguments' => $this->arguments]);
$exitCode = Artisan::call($this->command, $this->arguments);
$output = Artisan::output();
Log::info('Artisan command executed', [
'command' => $this->command,
'arguments' => $this->arguments,
'exitCode' => $exitCode,
'output' => $output,
]);
} catch (\Exception $e) {
Log::error('Artisan command failed', ['command' => $this->command, 'arguments' => $this->arguments, 'error' => $e->getMessage()]);
throw $e;
} finally {
$lock->release();
}
} else {
Log::warning('Artisan command is already running', ['command' => $this->command, 'arguments' => $this->arguments]);
}
}
}

总结

在 Laravel 中,虽然有多种方法可以中断程序执行,但在队列任务中应避免使用 exit() 和 die() 等会导致队列处理器停止的方法。相反,推荐使用抛出异常和锁机制来确保任务不会被多次执行。如果有任何其他问题或需求,请告诉我!


文章作者: Crazy Boy
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Crazy Boy !
赏

留言

想法、疑问或勘误,都可以写在这里。留言会公开显示。