Laravel 5.6 . 队列

6 篇文章 0 订阅

Laravel 队列为不同的后台队列服务提供了统一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基于关系型数据库的队列。队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短 Web 请求和响应的时间。

队列配置文件存放在 config/queue.php。每一种队列驱动的配置都可以在该文件中找到,包括数据库、BeanstalkdAmazon SQSRedis以及同步(本地使用)驱动。其中还包含了一个 null 队列驱动用于那些放弃队列的任务。

连接 Vs. 队列

在开始使用 Laravel 队列以前,了解“连接”和“队列”的关系非常重要。在配置文件 config/queue.php 有一个 connections 配置项。该配置项定义了后台队列服务的特定连接,如 Amazon SQS, Beanstalk, 或 Redis。每种队列连接都可以有很多队列,可以想象在银行办理现金业务的各个窗口队列。

请注意 queue 配置文件中的每个连接配置示例都有一个 queue 属性。当新的队列任务被添加到指定的连接时,该配置项的值就是默认监听的队列(名称)。换种说法,如果你没有指派特别的队列名称,那么 queue 的值,也是该任务默认添加到的队列(名称):

//以下的任务将被委派到默认队列...

dispatch(new Job);

//以下任务将被委派到"email"队列...

dispatch((new Job)->onQueue('email'));

有些应用并不需要将任务分配到多个队列,单个队列已经非常适用。但是,应用的任务有优先级差异或者类别差异的时候,推送任务到多个队列将是更好地选择,因为 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 队列连接使用 Redis Cluster(集群),队列名称必须包含 key hash tag,以确保给定队列对应的所有 Redis keys 都存放到同一个 hash slot:

'redis' => [

     'driver' => 'redis' ,

     'connection' => 'default' ,

    'queue' => '{default}' ,

   'retry_after' => 90 ,

],

学院君注:对一般中小型应用推荐使用 Redis 作为队列驱动。

阻塞

使用 Redis 队列时,可以使用 block_for 配置项来指定驱动在迭代队列进程循环并重新轮询 Redis 数据库之前等待可用队列任务的时间。根据队列负载来调整此配置值会比轮询 Redis 数据库来查找新任务更加高效。例如,你可以设置该值为 5 来告诉驱动在等待可用队列任务时需要阻塞五秒:

'redis' => [

    'driver' => 'redis' ,

    'connection' => 'default' ,

    'queue' => 'default' ,

    'retry_after' => 90 ,

   'block_for' => 5,

]

注:阻塞是一个实验性功能,如果 Redis 服务器或队列进程与检索队列任务同时崩溃,那么队列任务有可能会丢失。

创建任务

生成任务类

通常,所有的任务类都保存在 app/Jobs 目录。如果 app/Jobs 不存在,在运行 Artisan 命令 make:job 的时候,它将会自动创建。你可以通过 Artisan CLI 来生成队列任务类:

php artisan make:job ProcessPodcast

生成的类都实现了 Illuminate\Contracts\Queue\ShouldQueue 接口, 告诉 Laravel 将该任务推送到队列,而不是立即运行:

任务类结构

任务类非常简单,通常只包含处理该任务的 handle 方法,让我们看一个任务类的例子。在这个例子中,我们模拟管理播客发布服务,并在发布以前上传相应的播客文件:

在本示例中,我们将 Eloquent 模型作为参数直接传递到构造函数。因为该任务使用了 SerializesModels trait,Eloquent 模型将会在任务被执行时优雅地序列化和反序列化。如果你的队列任务在构造函数中接收 Eloquent 模型,只有模型的主键会被序列化到队列,当任务真正被执行的时候,队列系统会自动从数据库中获取整个模型实例。这对应用而言是完全透明的,从而避免序列化整个 Eloquent 模型实例引起的问题。

handle 方法在任务被处理的时候调用,注意我们可以在任务的 handle 方法中进行依赖注入。Laravel 服务容器会自动注入这些依赖。

注:二进制数据,如原生图片内容,在传递给队列任务之前先经过 base64_encode 方法处理,此外,该任务被推送到队列时将不会被序列化为 JSON 格式。

分发任务

创建好任务类后,就可以通过任务自身的 dispatch 方法将其分发到队列。dispatch 方法需要的唯一参数就是该任务的实例:

ProcessPodcast::dispatch($podcast);

延时分发

有时候你可能想要延迟队列任务的执行,这可以通过在分发任务时使用 delay 方法实现。例如你希望将某个任务在创建 10 分钟以后才执行:

ProcessPodcast::dispatch($podcast)->delay(now()->addMinutes(10));

注:Amazon SQS 的队列服务最长延时 15 分钟。

任务链

任务链允许你指定一个需要在一个序列中执行的队列任务列表,如果序列中的某个任务失败,其它任务将不再运行。要执行一个队列任务链,可以使用任意可分发任务上的 withChain 方法:

ProcessPodcast::withChain([

    new OptimizePodcast ,

   new ReleasePodcast

])->dispatch();

链接连接 & 队列

如果你想要指定任务链使用的默认连接和队列,可以使用 allOnConnection 和 allOnQueue 方法。这些方法指定队列连接和队列名称

自定义队列 & 连接

分发到指定的队列

通过推送任务到不同队列,你可以将队列任务进行“分类”,甚至根据优先级来分配每个队列的进程数。请注意,这并不意味着使用了配置项中那些不同的连接来管理队列,实际上只有单一连接会被用到。要指定队列,请在任务实例使用 onQueue 方法:

ProcessPodcast::dispatch($podcast)->onQueue('processing');

分发到指定的连接

如果你使用了多个连接来管理队列,那么可以分发任务到指定的连接。请在任务实例中使用 onConnection 方法来指定连接:

ProcessPodcast::dispatch($podcast)->onConnection('sqs');

当然,你可以同时使用 onConnection 和onQueue 方法来指定任务的连接和队列:

$job = (new ProcessPodcast($podcast))->onConnection('sqs')->onQueue('processing');

指定最大失败次数/超时时间

最大失败次数

指定队列任务最大失败次数的一种实现方式是通过 Artisan 命令 --tries 切换:

php artisan queue:work --tries=3

不过,你还可以在任务类自身定义最大失败次数来实现更加细粒度的控制,如果最大失败次数在任务中指定,则其优先级高于命令行指定的数值:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值