简介
Laravel 队列为不同的后台队列服务提供了统一的 API,例如 Beanstalk,Amazon SQS,Redis,甚至其他基于关系型数据库的队列。
队列的目的是将耗时的任务延时处理,比如发送邮件,从而大幅度缩短 Web 请求和响应的时间。
队列的配置文件存放在 config/queue.php。
每一种队列驱动的配置都可以在该文件中找到,包括数据库、Beanstalkd、Amazon SQS、Redis以及sync同步(本地使用)驱动。其中还包含了一个 null 队列驱动用于那些放弃队列的任务。
sync 同步驱动是指采用同步队列的方式执行任务,它是 Laravel 队列的默认配置。(开发环境建议使用 sync 同步驱动,方便调试。)
注:Laravel 现在提供了基于 Redis 的,拥有美观的后台和配置系统的 Horizon 队列扩展包,完整信息请参考 Horizon文档。
连接
首先,我们必须知道连接和队列的关系。
在配置文件 config/queue.php 中,有一个 connections 配置项。该配置项定义了后台队列服务的特定连接,如 Amazon SQS、Redis、Database 等。
每种连接都可以有很多队列,可以想象在银行办理现金业务的各个窗口队列。
配置文件中的每个连接配置示例都有一个 queue 属性。当新的队列任务被添加到指定的连接时,该配置项的值就是默认监听的队列名称。如果你没有指定队列名称,那么 queue 的值,就是该任务默认添加到的队列名称。
queue 的值默认为 default。
// 以下的任务将被委派到默认队列
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
之后,就会自动在对应的数据库中创建下面的 jobs 表。
CREATE TABLE `jobs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`queue` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
`payload` longtext COLLATE utf8mb4_unicode_ci NOT NULL,
`attempts` tinyint(3) unsigned NOT NULL,
`reserved_at` int(10) unsigned DEFAULT NULL,
`available_at` int(10) unsigned NOT NULL,
`created_at` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
KEY `jobs_queue_index` (`queue`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
分发(委派)任务后,任务会被自动保存到 jobs 表。
当运行队列进程时,就可以处理队列中的任务。如果任务处理(handle方法)过程中没有抛出异常,则认为该任务处理成功,队列中的任务就会被自动删除。如果 handle 方法中有异常抛出,该任务会重新回到队列自动重试,直到达到最大尝试次数,之后会从 jobs 表中删除,转而存储到 failed_jobs 表。
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 方法,让我们看一个任务类的例子。
<?php
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 Int