队列允许你延迟处理耗时任务,例如发送电子邮件,直到稍后,从而大幅加快你的应用的 Web 请求。
队列配置文件存储在config/queue.php。在此文件中,你将找到所包含的每个队列驱动程序的连接配置,例如数据库,Beanstalkd,Amazon SQS,Redis,null,以及同步(用于本地使用)驱动。该null队列驱动程序会简单地丢弃排队的作业因此它们永远不会被执行。
列出的队列驱动程序需要以下依赖项。这些依赖项可以通过 Composer 包管理器进行安装。
| Connection | Package |
|---|---|
| Amazon SQS | aws/aws-sdk-php ~3.0 |
| Beanstalkd | pda/pheanstalk ~4.0 |
| Redis | predis/predis ~1.0 or phpredis PHP extension |
要将新作业推送到队列中,请使用 Queue::push 方法。
Queue::push(SendEmail::class, ['message' => $message]);传入 push 方法的第一个参数是用于处理该作业的类的名称。第二个参数是应传递给处理程序的数据数组。一个作业处理程序可以定义为文件 app/SendEmail.php 如下所示。
class SendEmail
{
public function fire($job, $data)
{
//
}
}请注意,唯一必需的方法是 fire,它接收一个 Job 实例以及一个被推送到队列的 data 数组。如果你希望这个作业使用除了 fire 之外的方法,你可以在推送作业时指定该方法:
Queue::push('SendEmail@send', ['message' => $message]);您也可以指定作业应发送到的队列 / 管道:
Queue::push('SendEmail@send', ['message' => $message], 'emails');有时你可能希望延迟一个排队任务的执行。例如,你可能希望在用户注册 15 分钟后,排队发送一封电子邮件给客户的任务。你可以使用 Queue::later 方法来完成此操作:
$date = Carbon::now()->addMinutes(15);
Queue::later($date, 'SendEmail', ['message' => $message]);在这个例子中,我们正在使用 Carbon 日期库来指定我们希望分配给该任务的延迟。或者,你可以传入你希望延迟的秒数作为整数。
注意:
Amazon SQS 服务具有 900 秒 (15 分钟) 的延迟上限。
如果您的排队任务在其数据中包含一个模型,只有该模型的标识符会被序列化到队列中。当任务实际被处理时,队列系统将自动从数据库中重新检索完整的模型实例。这对您的应用程序来说是完全透明的,并且可以避免因序列化完整模型实例而可能出现的问题。
一旦你处理完一个作业,它必须从队列中删除,这可以通过 Job 实例上的 delete 方法来完成:
public function fire($job, $data)
{
// Process the job...
$job->delete();
}如果您希望将一个任务释放回队列,您可以通过 release 方法来完成:
public function fire($job, $data)
{
// Process the job...
$job->release();
}您还可以指定任务释放前等待的秒数:
$job->release(5);如果作业正在处理过程中发生异常,它将自动返回到队列中。您可以使用 attempts 方法检查尝试运行作业的次数:
if ($job->attempts() > 3) {
//
}您也可以访问作业标识符:
$job->getJobId();您也可以将一个闭包推送到队列中。这对于需要排队执行的快速、简单任务来说非常方便:
Queue::push(function($job) use ($id) {
Account::delete($id);
$job->delete();
});与其通过
use指令将对象提供给排队的闭包,不如考虑传递主键,并在你的队列任务中重新拉取关联的模型。这通常可以避免意想不到的序列化行为。
October CMS 包含一些控制台命令,用于处理队列中的作业。要处理当新作业被推入队列时,请运行 queue:work 命令:
php artisan queue:work一旦此任务启动,它将继续运行,直到它被手动停止。您可以使用进程监视器,例如 Supervisor,以确保队列工作器不会停止运行。
队列工作进程将启动的应用程序状态存储在内存中。它们在启动后不会识别到您的代码更改。部署更改时,请重启队列工作进程。
要仅处理队列中的第一个作业,请使用 --once 选项:
php artisan queue:work --once您也可以指定 worker 应该使用哪个队列连接:
php artisan queue:work --once connection您可以将一个逗号分隔的队列连接列表传递给 work 命令,以设置队列优先级:
php artisan queue:work --once --queue=high,low在此示例中,high 队列中的作业将始终被处理,然后才会处理 low 队列中的作业。
您还可以设置每个作业允许运行的时长(以秒为单位):
php artisan queue:work --once --timeout=60此外,您可以指定在轮询新作业之前等待的秒数:
php artisan queue:work --once --sleep=5请注意,队列只有在没有作业时才会“休眠”。 如果有更多作业可用,队列将继续处理它们而不会休眠。
默认情况下,queue:work 将处理任务,而无需重新启动框架。与 queue:work --once 命令相比,这可显著降低 CPU 使用率,但增加了在部署期间需要清空当前正在执行任务的队列的复杂性。
若要以守护进程模式启动队列工作器,只需省略 --once 标志:
php artisan queue:work connection
php artisan queue:work connection --sleep=3
php artisan queue:work connection --sleep=3 --tries=3您可以使用 php artisan help queue:work 命令来查看所有可用的选项。
部署使用守护进程队列工作者的应用程序最简单的方式,是在部署开始时将应用程序置于维护模式。这可以通过使用后端设置区域来完成。一旦应用程序处于维护模式,October 将不会从队列中接受任何新作业,但会继续处理现有作业。
重启您的工作进程最简单的方法是,在您的部署脚本中包含以下命令:
php artisan queue:restart此命令将指示所有队列工作者在它们完成处理当前任务后重新启动。
此命令依赖于缓存系统来安排重启。默认情况下,APCu 不适用于 CLI 命令。如果您正在使用 APCu,请将
apc.enable_cli=1添加到您的 APCu 配置中。
守护队列工作进程在处理每个作业之前不会重启平台。因此,您应该注意在作业完成之前释放所有占用大量资源的项。例如,如果您正在使用 GD 库进行图像处理,在完成后应使用 imagedestroy 释放内存。
同样地 您的数据库连接在被长时间运行的守护进程使用时可能会断开连接。您可以使用 Db::reconnect 方法来确保您获得一个全新的连接。
Supervisor 是 Linux 操作系统的进程管理器,如果 queue:work 进程失败,它将自动重启该进程。要在 Ubuntu 上安装 Supervisor,您可以使用以下命令:
sudo apt-get install supervisorSupervisor 配置文件通常存储在 /etc/supervisor/conf.d 目录中。在此目录中,您可以创建任意数量的配置文件,用于指示 Supervisor 如何监控您的进程。例如,让我们创建一个 october-worker.conf 文件,用于启动和监控一个 queue:work 进程。
[program:october-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /path/to/october/artisan queue:work --sleep=3 --tries=3
autostart=true
autorestart=true
user=october
numprocs=8
redirect_stderr=true
stdout_logfile=/path/to/october/worker.log在此示例中,numprocs 指令将指示 Supervisor 运行 8 个 queue:work 进程并监控所有这些进程,如果它们失败,则自动重启它们。当然,您应该更改命令指令中 queue:work 部分,以反映您所需的队列连接。user 指令应更改为具有运行该命令权限的用户名称。
一旦配置文件创建完成,您可以更新 Supervisor 配置并启动进程,使用以下命令:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start october-worker:*有关 Supervisor 的更多信息,请查阅 Supervisor 文档。
因为事情并非总按计划进行,有时你的队列任务会失败。别担心,这很常见!有一种便捷的方式来指定一个任务应被尝试的最大次数。当任务的尝试次数超出此数量后,它将被插入到 failed_jobs 表中。失败任务表的名称可以通过 config/queue.php 配置文件进行配置。
你可以指定作业的最大尝试次数 在 queue:work 命令上使用 --tries 开关:
php artisan queue:work connection-name --tries=3如果您想注册一个在队列任务失败时会被调用的事件,您可以使用 Queue::failing 方法。这个事件是一个很好的机会,可以通过电子邮件或其他第三方服务通知您的团队。
Queue::failing(function($connection, $job, $data) {
//
});您也可以直接在队列任务类上定义一个 failed 方法,允许您在发生故障时执行任务特定的操作:
public function failed($data)
{
// Called when the job is failing...
}原始数组 data 也将自动传递给失败方法。
要查看所有失败的作业,您可以使用 queue:failed Artisan 命令:
php artisan queue:failedqueue:failed 命令将列出作业 ID、连接、队列和失败时间。作业 ID 可用于重试失败的作业。例如,要重试 ID 为 5 的失败作业,应执行以下命令:
php artisan queue:retry 5如果您想删除一个失败的任务,您可以使用 queue:forget 命令:
php artisan queue:forget 5要删除所有失败的作业,您可以使用 queue:flush 命令:
php artisan queue:flush