一. 什么是队列
在构建 Web 应用程序时,你可能需要执行一些任务,例如解析文件,发送邮件,大量的数据计算等等,这些任务在典型的 Web 请求期间需要很长时间才能执行
。
庆幸的是,Laravel 可以创建在后台运行
的队列任务。 通过将时间密集型任务
移至队列,你的应用程序可以以极快的速度响应
Web 请求,并为你的客户提供更好的用户体验。
说人话:laravel可以轻松创建,后台运行的队列,再将耗时的任务移到队列,减少用户在页面上的等待时间,提高用户体验。
二. 配置队列驱动
队列驱动 就是 以哪个方式来处理队列任务。
常见的驱动如下:
1.sync 驱动 (同步)
.env 文件
编辑
php
QUEUE_CONNECTION=sync
特点是: 任务立即执行
,不进入队列, 适合开发和测试环境
,请求会阻塞
直到任务完成
我一般是本地和测试
使用,如果使用这个,那就跟队列没什么关系了,直接同步执行
2. database 驱动
php
QUEUE_CONNECTION=database
数据库驱动时,肯定首先需要创建数据表的。用来存储队列服务的。如下
php
php artisan queue:table
php artisan migrate
会创建两个表,存储任务数据
打开 config/queue.php
文件,配置一下
php
'database' => [
'driver' => 'database',
'table' => 'jobs',
'queue' => 'default',
'retry_after' => 90,
],
特点是:使用的是数据库存储
任务,不需要单独配置服务,有数据库即可
,适合中小规模项目
3. redis 驱动 (推荐)
php
QUEUE_CONNECTION=redis
打开 config/queue.php
文件,配置一下
php
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => env('REDIS_QUEUE', 'default'),
'retry_after' => 90,
'block_for' => null,
'after_commit' => false,
],
注意 :
利用 redis 做为驱动的话,前提一定要配置好 redis
。
特点:高性能
,适合生产环境
, 支持队列优先级
其他的驱动,暂时不做说明,大家可以自己去研究下。
三.创建队列任务
1. 生成任务类
php
php artisan make:job ProjectJob
生成的文件位于 app/Jobs/ProjectJob.php
2.任务类开发逻辑
php
<?php
namespace App\Jobs;
use App\Http\Services\ProjectService;
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 ProjectJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public array $reqData;
/**
* 任务支持错误,可尝试的次数。
*
* @var int
*/
public $tries = 5;
/**
* Create a new job instance.
*/
public function __construct($data = [])
{
$this->reqData = $data;
$this->onQueue('project-compute');
}
/**
* Execute the job.
*/
public function handle(): void
{
$data = $this->reqData;
// 开始发送邮件功能,大量耗时的任务开始编码
Log::info("===project-compute-Log===", [$data, $res]);
}
}
3.唯一任务实现
有时,希望这个队列在任务时间点,只有一个任务的实例,只需要实现 ShouldBeUnique 即可。
php
<?php
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUnique;
class ProjectJob implements ShouldQueue, ShouldBeUnique
{
public $Project;
/**
* 唯一锁将被释放的秒数
*
* @var int
*/
public $uniqueFor = 20;
/**
* 任务的唯一 ID
*/
public function uniqueId(): string
{
return $this->Project->id;
}
}
如上:同一个 Project->id 在 20 秒内,都会被忽略,当 20 秒后,相同的id任务会再次分配到队列
四. 分发队列任务
分发,也就是怎么在控制器里面 去 将任务 丢到队列。
1.基本分发方式
php
ProjectJob ::dispatch(['data':"123"]);
2.延迟分发,10分钟后
php
ProjectJob ::dispatch(['data':"123"])->delay(now()->addMinutes(10));;
3.同步分发,立即执行
php
ProjectJob ::dispatchSync(['data':"123"]);
4. 指定队列
php
ProjectJob ::dispatch(['data':"123"])->onQueue('high');
五. 队列工作进程管理
1. 启动队列工作进程
shell
php artisan queue:work

2. 常用选项
shell
# 指定队列连接
php artisan queue:work --queue=high
php artisan queue:work --queue=high,default
--queue=high,default
是启动了一个工作进程
,但该进程会按照优先级处理多个队列中的任务
。
3. 重启队列
在队列的代码修改了,那么就需要重启队列。
shell
php artisan queue:restart
由于队列任务是长期存在
的进程,如果不重新启动
,他们不会注意
到代码的更改。
可以通过发出 queue:restart
命令优雅地重新启动所有进程
queue:restart 说明:
-
不是真正的进程重启:
-
不会终止或重新创建
现有的队列工作进程 -
不会改变进程ID
(PID)或端口 -
现有进程
会继续完成
当前正在处理的任务
-
-
优雅重启机制:
-
在存储系统(缓存/数据库)中
设置重启标记
-
工作进程在完成当前任务后
检查到标记
,会自行退出
-
进程管理器(如
Supervisor
)会自动重新启动
新进程
-
注意:
我的队列进程就是 用 Supervisor
托管的,所以在 queue:restart
后,Supervisor 会自动重启
我的队列进程。

当前队列进程启动后,在控制器内,丢入任务到队列,队列就会排队处理任务了。
如下图所示,队列的处理日志。
六. 处理失败的任务
在任务处理失败时,队列会先尝试在运行几次,见 2.任务类开发逻辑 的 tries 参数,超过
此尝试次数后,它将被插入到 failed_jobs
数据库表中
shell
php artisan queue:failed-table
php artisan migrate
可以使用 queue:failed-table
命令来创建迁移错误任务表
1.查看失败任务
shell
php artisan queue:failed
如图:
2. 重试失败的任务
shell
#重试单个任务id
php artisan queue:retry ce7bb17c-cdd8-41f0-a8ec-7b4fef4e5ece
# 重试多个任务id
php artisan queue:retry ce7bb17c-cdd8-41f0-a8ec-7b4fef4e5ece 91401d2c-0784-4f43-824c-34f94a33c24d
# 重试指定队列的所有失败任务
php artisan queue:retry --queue=name
#重试所有失败任务
php artisan queue:retry all
执行后

3.清理失败任务
shell
#要删除指定的失败任务
php artisan queue:forget 91401d2c-0784-4f43-824c-34f94a33c24d
# 删除 failed_jobs 表中所有失败任务
php artisan queue:flush
如图
通过以上配置和使用方法,你可以充分利用Laravel队列系统来提高应用性能和用户体验。
在实际的使用中,会遇到各种问题,大家可以自行去拓展,里面有很多的参数设置和功能,我这边就不一一去说明,边用边学。