Laravel 队列系统实现及使用教程
由 学院君 创建于2年前, 最后更新于 9个月前
版本号 #2
48088 views
10 likes
0 collects
简介
注:Laravel 现在提供了基于 Redis 的,拥有美观的后台和配置系统的 Horizon 队列扩展包,完整信息参考 Horizon文档。
Laravel 队列为不同的后台队列服务提供了统一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基于关系型数据库的队列。队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短 Web 请求和响应的时间。
队列配置文件存放在 config/queue.php。每一种队列驱动的配置都可以在该文件中找到,包括数据库、Beanstalkd、Amazon SQS、Redis以及同步(本地使用)驱动。其中还包含了一个 null 队列驱动用于那些放弃队列的任务。
连接 Vs. 队列
在开始使用 Laravel 队列以前,了解“连接”和“队列”的关系非常重要。在配置文件 config/queue.php 有一个 connections 配置项。该配置项定义了后台队列服务的特定连接,如 Amazon SQS, Beanstalk, 或 Redis。每种队列连接都可以有很多队列,可以想象在银行办理现金业务的各个窗口队列。
请注意 queue 配置文件中的每个连接配置示例都有一个 queue 属性。当新的队列任务被添加到指定的连接时,该配置项的值就是默认监听的队列(名称)。换种说法,如果你没有指派特别的队列名称,那么 queue 的值,也是该任务默认添加到的队列(名称):
// 以下的任务将被委派到默认队列...
dispatch(new Job);
// 以下任务将被委派到 "emails" 队列...
dispatch((new Job)->onQueue('emails'));
有些应用并不需要将任务分配到多个队列,单个队列已经非常适用。但是,应用的任务有优先级差异或者类别差异的时候,推送任务到多个队列将是更好地选择,因为 Laravel 的队列进程支持通过优先级指定处理的队列。举个例子,你可以将高优先级的任务委派到 high (高优先级)队列,从而让它优先执行。
php artisan queue:work --queue=high,default
驱动预备知识
数据库
要使用 database 队列驱动,你需要数据表保存任务信息。要生成创建这些表的迁移,可以运行 Artisan 命令 queue:table,迁移被创建之后,可以使用 migrate 命令生成这些表:
php artisan queue:table
php artisan migrate
Redis
要使用 redis 队列驱动,需要在配置文件 config/database.php 中配置 Redis 数据库连接。
如果 Redis 队列连接使用 Redis Cluster(集群),队列名称必须包含 key hash tag,以确保给定队列对应的所有 Redis keys 都存放到同一个 hash slot:
'redis' => [
'driver' => 'redis',
'connection' => 'default',
'queue' => '{default}',
'retry_after' => 90,
],
注:对一般中小型应用推荐使用 Redis 作为队列驱动。
其他驱动预备知识
如果使用以下几种队列驱动,需要安装相应的依赖:
Amazon SQS: aws/aws-sdk-php ~3.0
Beanstalkd: pda/pheanstalk ~3.0
Redis: predis/predis ~1.0
创建任务
生成任务类
通常,所有的任务类都保存在 app/Jobs 目录。如果 app/Jobs 不存在,在运行 Artisan 命令 make:job 的时候,它将会自动创建。你可以通过 Artisan CLI 来生成队列任务类:
php artisan make:job ProcessPodcast
生成的类都实现了 Illuminate\Contracts\Queue\ShouldQueue 接口, 告诉 Laravel 将该任务推送到队列,而不是立即运行:
任务类结构
任务类非常简单,通常只包含处理该任务的 handle 方法,让我们看一个任务类的例子。在这个例子中,我们模拟管理播客发布服务,并在发布以前上传相应的播客文件:
namespace App\Jobs;
use App\Podcast;
use App\AudioProcessor;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class ProcessPodcast implements ShouldQueue
{
use InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* 创建任务实例
*
* @param Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* 执行任务