一,构建
1. lumen利用Laravel的队列组件为各种不同的队列服务提供统一的API。队列允许将耗时任务(例如发送电子邮件)的处理推迟到稍后的时间,从而大大加快了对应用程序的web请求。
lumen和laravel提供了数据库,Beanstalked, IronMQ, Amazon SQS, Redis, null, 和同步队列驱动(供本地使用)的支持。空队列驱动程序只是丢弃队列的作业,因此它们永远不会运行。
2. .env文件中的QUEUE_DRIVER选项决定了应用程序将使用的队列驱动。
例如:
QUEUE_DRIVER=redis
QUEUE_REDIS_CONNECTION=redis_queue
3. 为了使用数据库队列驱动程序,您需要一个数据库表来保存作业。表架构应如下所示:
4. 其他队列依赖
队列驱动程序需要以下依赖项:
Amazon SQS: aws/aws-sdk-php
Beanstalkd: pda/pheanstalk~3.0
IronMQ: iron-io/iron_mq~1.5
Redis: predis/predis~1.0
二, 基本用法
1. 推送一个作业到队列中
应用程序的所有可排队作业都存储在 App\Jobs 目录中。基类 App\Job 可以作为其余任务的基类。
注意:如果您打算使用 Queue facade,请务必取消注释 bootstrap/app.php 文件中的 $app->withFacades() 调用。
2. 要将新作业推送到队列中,请使用 Queue::push 方法:
Queue::push(newSendEmail($message));
你也可以使用闭包路由或控制器的 dispatch 方法:
$this->dispatch(newSendEmail($message));
3. 当作业被队列执行时,作业的句柄方法将被调用。您可以在句柄方法上键入提示您需要的任何依赖项,服务容器将自动注入它们:
4. 为作业(job)指定队列(queue)/Tube
Queue::pushOn('emails',newSendEmail($message));
5. 将相同的负载(payload)传递给多个作业(job)
如果您需要将相同的数据传递给多个队列作业(queue job),您可以使用 Queue::bulk 方法:
Queue::bulk([newSendEmail($message),newAnotherCommand]);
6. 延迟作业的执行
有时您可能希望延迟正在排队的队列作业的执行。例如,您可能希望注册一个15 分钟后将向客户发送电子邮件的队列作业。您可以使用 Queue::later 方法完成此操作:
$date=Carbon::now()->addMinutes(15);
Queue::later($date, newSendEmail($message));
在此示例中,我们使用 Carbon 日期库来指定我们希望分配给作业的延迟。或者,您可以将希望延迟的秒数作为整数传递。
7. 队列和 Eloquent 模型(Queues And Eloquent Models)
如果您的队列作业在其构造函数中接受 Eloquent Model,则只有模型的标识符将被序列化到队列中。当实际处理作业时,队列系统会自动从数据库中重新检索完整的模型实例。这对您的应用程序完全透明,并且可以防止序列化完整的 Eloquent 模型实例可能出现的问题。
8. 删除已处理的队列作业
处理完作业后,必须将其从队列中删除。如果在你的工作执行过程中没有抛出异常,这将自动完成。
如果您想手动删除或释放作业,Illuminate\Queue\InteractsWithQueue trait 提供对队列任务释放和删除方法的访问。 release 方法接受一个值:您希望等待作业再次可用的秒数。
9. 将任务释放回队列
如果正在处理的任务发生了异常,它将自动释放回队列,以便再次尝试。该任务将继续释放,直到应用程序允许的最大尝试次数。最大尝试次数由---- Artisan任务:queue:listen或queue:work 使用的tries开关定义
10. 检查尝试运行次数
如果正在处理的任务发生异常,它将自动释放回队列。您可以尝试方法检查运行任务的尝试次数:
if($this->attempts() > 3){
}
注意:您的任务/句柄必须引用Illuminate\Queue\InteractsWithQueue才能调用此方法
三,更多调度方法
从请求映射命令属性
将HTTP请求变量映射到任务(jobs)中是非常常见的。因此lumen提供了一些辅助方法,使其成为一种便捷的方式,而不是强制您为每个请求手动执行此操作。让我们看一下来自闭包路由和控制器方法的dispatchFrom 方法
$this->dispatchFrom('Command\Class\Name',$request);
此方法将检查任务类的构造函数,然后从HTTP请求(或任何其他ArrayAccess对象)中提取变量,以填充任务所需的构造函数参数。因此,如果我们的任务类在其构造函数中接受firstName变量,任务总线将尝试从HTTP请求中提取firstName参数。
还可以将数组作为第三个参数传递给dispatchFrom方法。此数组将用于填充请求中不可用的任何构造函数参数:
$this->dispatchFrom('Command\Class\Name',$request,[
'firstName'=>'Taylor',
]);
四,排队闭包
注意:在对闭包进行排队之前,需要添加jeremeamia/superclosure (~2.0)到composer.json文件中
您还可以将闭包推到队列上。这对于需要排队的快速简单任务非常方便:
将闭包推到队列上
Queue::push(function($job) use($id){
Account::delete($id);
$job->delete();
});
注意:不要通过使用指令使闭包队列对象可用,请考虑传递主键并从队列作业中重新提取相关模型。这通常可以避免意外的序列化行为。
当使用Iron.io推送队列时,你应该采取额外的预防措施排队闭包。接收队列消息的端点(end-point)应该检查token,以验证请求实际上来自Iron.io。例如,推送队列的端点(end-point)应该是:https://yourapp.com/queue/receive?token=SecretToken。然后,您可以在封送(marshalling)队列请求之前检查应用程序中的秘密令牌(secret token)的值。
五,运行队列监听器
Lumen和Laravel一样,包括一个Artisan任务,当新作业被推到队列中时,该任务将运行新作业。您可以通过使用queue:listen运行此任务
1. 开启队列监听器
php artisan queue:listen
您还可以指定监听器应使用的队列连接:
php artisan queue:listen connection
请注意,一旦此任务启动,它将继续运行,直到手动停止。您可以使用进程监视器(如Supervisor)来确保队列监听器不会停止运行。
您可以将以逗号分隔的队列连接列表传递给监听器作业,以设置队列优先级:
php artisan queue:listen--queue=high,low
在本例中,高连接(high-connection)上的作业将始终在从低连接(low-connection)转移到作业之前进行处理。
2. 指定作业超时参数
您还可以设置每个作业应允许运行的时间长度(以秒为单位):
php artisan queue:listen--timeout=60
3. 指定队列睡眠持续时间
此外,您可以指定在轮询新作业之前等待的秒数:
php artisan queue:listen--sleep=5
请注意,只有当队列中没有作业时,队列才会“休眠”。如果有更多的作业可用,队列将继续工作而不“休眠”。
4. 正在处理队列上的第一个作业
要仅处理队列上的第一个作业,可以使用queue:work作业
php artisan queue:work
六,守护进程队列工作程序
queue:work还包括一个--daemon选项,用于强制queue worker在不重新启动框架的情况下继续处理作业。与queue:listen作业相比,这会显著减少CPU使用量。
要在守护程序模式下启动队列工作程序,请使用--daemon标志:
php artisan queue:work connection--daemon
php artisan queue:work connection--daemon--sleep=3
php artisan queue:work connection--daemon--sleep=3--tries=3
如您所见,queue:work作业支持queue:listen可用的大部分相同选项。您可以使用php artisan help queue:work job查看所有可用选项。
1. 使用守护进程队列工作程序部署
使用守护进程队列工作程序部署应用程序的最简单方法是在部署开始时将应用程序置于维护模式。这可以使用php artisan down作业来完成。一旦应用程序处于维护模式,Lumen和Laravel将不接受队列外的任何新作业,但将继续处理现有作业。
重启workers的最简单方法是在部署脚本中包含以下作业:
php artisan queue:restart
此作业将指示所有队列在完成当前作业的处理后重新启动。
注意:此作业依赖缓存系统来安排重新启动。默认情况下,APCu不适用于CLI作业。如果您正在使用APCu,请在APCu配置添加apc.enable_cli=1。
2. 为守护进程队列工作程序编写代码
守护进程队列工作程序在处理每个作业之前不会重新启动框架。因此,在工作完成之前,你应该小心地释放任何沉重的资源。例如,如果您正在使用GD库进行图像处理,那么在完成操作时,应该使用imagedestroy 释放内存。
类似地,当被长时间运行的守护程序使用时,数据库连接可能会断开。您可以使用DB::reconnect方法来确保有一个新的连接。
七,失败作业
由于事情并不总是按计划进行,有时排队的作业会失败。Lumen和Laravel提供了一种方便的方法来指定作业的最大尝试次数。作业超过此尝试次数后,它将被插入failed_jobs表中。
1. failed_jobs表应具有如下模式:
Schema::create('failed_jobs',function(Blueprint$table)
{
$table->increments('id');
$table->text('connection');
$table->text('queue');
$table->text('payload');
$table->timestamp('failed_at');
});
2. 您可以通过使用queue:listen作业上使用--tries开关,指定作业的最大尝试次数:
php artisan queue:listen connection-name--tries=3
3. 如果要注册队列作业失败时将调用的事件,可以使用Queue::failing方法。这个事件是通过电子邮件或HipChat通知团队的绝佳机会。
Queue::failing(function($connection,$job,$data){
});
4. 您还可以直接在队列作业类上定义失败的方法,以便在发生故障时执行特定操作:
public function failed()
{
// Called when the job is failing...
}
5. 重试失败作业
要查看所有失败作业,你可以使用Artisan作业:queue:failed
php artisan queue:failed
queue:failed将列出作业ID、连接、队列和失败时间。作业ID可用于重试失败的作业。例如,要重试ID为5的失败作业,应发出以下作业:
php artisan queue:retry 5
如果要删除一个失败队列,可以使用queue:forget作业:
php artisan queue:forget 5
要删除所有的失败队列,可以使用queue:flush作业:
php artisan queue:flush