笔记:任务队列的简单使用
写在前面
Laravel 队列
系统是通过将耗时
的任务(如发送邮件、处理大型文件等)放入队列中,然后由后台进程异步执行
这些任务,从而提高性能和响应速度。
框架支持多种队列驱动,包括数据库、Redis、Amazon SQS、Beanstalkd 等。
快速开始
这里仅对 队列任务
做简单的快速入门使用,更多了解与使用请阅读官方文档!
参考文档:队列《Laravel 9 中文文档》
队列工作
队列是一个后台进程,负责监听队列并处理队列中的任务/Job
。当有新任务被推送到队列时,队列会自动取出并执行相应的任务逻辑。
通常需要会配合 Supervisor
来确保队列任务进程一直处于存活状态!
启动队列:
php artisan queue:work --daemon
队列连接
Laravel 支持多种队列驱动,包括数据库、Redis、Amazon SQS、Beanstalkd 等。在配置文件 config/queue.php 中配置。
通常选择 Redis
或 database
,一般情况下,我们选择 Redis
队列驱动。
QUEUE_CONNECTION=redis
配置失败的队列 job 表:failed_jobs
# failed_jobs
php artisan queue:failed-table
php artisan migrate
如果选择 database
驱动,则需要创建任务表:jobs
# 创建表 jobs
php artisan queue:table
php artisan migrate
队列任务
创建一个队列任务 Job 命令:
php artisan make:job SendMsg
此命令会在 app/Jobs/
路径下生成任务类 SendMsg.php
,任务类有一个 handle 方法,用来处理任务业务逻辑。
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Throwable;
class SendMsg implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private string $phone;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct(string $phone)
{
$this->phone = $phone;
}
/**
* 获取一个可以被传递通过的中间件任务
*
* @return array
*/
public function middleware(): array
{
return [
new RateLimited(),
new WithoutOverlapping()
];
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
Log::info('SendMsg Job Started');
sleep(10);
Log::info('SendMsg Job finished');
}
/**
* 任务失败时的处理逻辑
* 如:发送通知
* @param Throwable $exception
* @return void
*/
public function failed(Throwable $exception)
{
Log::info('SendMsg Job Failed');
}
}
调度任务
任务使用 dispatch()
函数来分发一个队列任务。传递给 dispatch()
的参数将被传递给任务的构造函数,调度过程中可指定连接,队列,延迟调度等等。
参考:队列《Laravel 9 中文文档》
需要注意:
- 确保任务实际上能够执行成功;
- 任务类本身的 dispatch() 来调度,传递给 dispatch() 的参数(动态参数)将被传递给任务的构造函数,任务类注意接收;
- 特别说一个配置参数 ‘after_commit’ => false, 一般不要在配置文件修改!如果确实需要在所有数据库事务提交后才调度任务,可以使用 afterCommit() 方法;
- 任务链
chain()
方法,任务依赖于其他多个顺序运行的任务
时,一个任务失败则其他任务都不会执行;- 使用任务类的 ::withChain([new x1(), new x2()]) 方法
- 或者 Illuminate\Support\Facades\Bus::chain([]) 方法
参考代码:
public function test(Request $request)
{
$phone = '13011223344';
// 调度任务
SendMsg::dispatch($phone)->afterCommit();
//SendMsg::withChain([])->dispatch();
//Bus::chain([])->dispatch();
}
队列中间件
Laravel 任务中间件允许你围绕排队任务的执行封装自定义逻辑,从而减少了任务本身的代码。一般基本不会使用,但
参考代码:
<?php
namespace App\Jobs\Middleware;
use Illuminate\Support\Facades\Redis;
class RateLimited
{
/**
* 处理队列任务
*
* @param mixed $job
* @param callable $next
* @return mixed
*/
public function handle($job, $next)
{
Redis::throttle('key')
->block(0)->allow(1)->every(5)
->then(function () use ($job, $next) {
// 获得了锁
$next($job);
}, function () use ($job) {
// 没有获取到锁
$job->release(5);
});
}
}
其他
核心源码参考:Illuminate\Foundation\Bus\Dispatchable
,Illuminate\Bus\Queueable
;
Laravel 队列任务
不仅仅是异步任务逻辑实现,更是一种解决方案。在日常使用中,除了 发送邮件
、处理大型文件
等 异步
场景外,更多的是配合 事件系统
的使用,这使得程序更加便捷健壮,也更加容易管理!
本作品采用《CC 协议》,转载必须注明作者和本文链接