队列允许你延迟处理一个耗时任务,例如发送电子邮件,直到稍后时间,从而大幅加快到你的应用程序的 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你也可以指定工作器应该使用哪个队列连接:
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 将处理作业而无需重启框架。 这导致 CPU 使用率显著降低, 相比 queue:work --once 命令, 但增加了在部署期间需要排空当前正在执行的作业队列的复杂性。
要以守护进程模式启动队列工作器,只需省略--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