一、 依赖的服务
IlluminateQueueQueueServiceProvider
队列服务由服务提供者QueueServiceProvider注册。 - registerManager() 注册队列管理器,同时添加 Null/Sync/Database/Redis/Beanstalkd/Sqs 连接驱动 - Null:不启动队列,生产者产生的任务被丢弃 - Sync:同步队列,生产者产生的任务直接执行 - Database:数据库队列驱动,生产者产生的任务放入数据库 - Redis:Redis队列驱动,生产者产生的任务放入Redis - Beanstalkd:略过 - Sqs:略过 - registerConnection() 注册队列连接获取闭包,当需要用到队列驱动连接时,实例化连接 - registerWorker() 注册队列消费者 - registerListener() Listen模式注册队列消费者 - registerFailedJobServices() 注册失败任务服务
|注册方法|对象|别名| |----|----|---| | QueueServiceProvider::registerManager() | IlluminateQueueQueueManager::class |queue| | QueueServiceProvider::registerConnection() | IlluminateQueueQueue::class |queue.connection| | QueueServiceProvider::registerWorker() | IlluminateQueueWorker::class |queue.worker| | QueueServiceProvider::registerListener() | IlluminateQueueListener::class |queue.listener| | QueueServiceProvider::registerFailedJobServices() | IlluminateQueueFailedFailedJobProviderInterface::class |queue.failer|
IlluminateBusBusServiceProvider
这个服务提供者注册了Dispatcher这个服务,可以将具体的任务派发到队列。
二、 任务机制
一个可放入队列的任务类:
<?php
use IlluminateBusQueueable;
use IlluminateQueueSerializesModels;
use IlluminateQueueInteractsWithQueue;
use IlluminateContractsQueueShouldQueue;
use IlluminateFoundationBusDispatchable;
class Job implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
}
任务在队列中需要经过两个过程:一个是任务入队,就是将要执行的任务,放到队列中去的过程,所有会发生这一过程的业务、对象、调用等等,可以统称为生产者;与之对应的,将任务从队列中取出,并执行的过程,叫做任务出队,所有会发生这一过程的业务、对象、调用等等,可以统称为消费者。
2.1 任务的要素
2.1.1 IlluminateFoundationBusDispatchable
这个trait给任务添加了两个静态方法dispatch/withChain
,赋予了任务派发的接口。 1. dispatch
dispatch方法触发任务指派动作。当执行 Job::dispatch()
时,会实例化一个IlluminateFoundationBusPendingDispatch
对象PendingDispatch
,并且将任务调用类实例化后的对象job
当作构造函数的参数:
// IlluminateFoundationBusDispatchable::trait
public static function dispatch()
{
// 这里的static转发到实际执行dispath的类 Job::dispatch,也就是Job类
return new PendingDispatch(new static(...func_get_args()));
}
PendingDispatch
对象接下来可以通过链式调用来指定队列相关信息 onConnection/onQueue/allOnConnection/allOnQueue/delay/chain
,然后在析构函数中,做实际的派发动作:
// IlluminateFoundationBusPendingDispatch::class
public function __destruct()
{
// IlluminateContractsBusDispatcher
// 这个服务由IlluminateBusBusServiceProvider注册
app(Dispatcher::class)->dispatch($this->job);
}
PendingDispath
这个中间指派者的作用,就是引出这里从容器中解析出来的服务Dispatcher::class
,真正的任务指派者Dispatcher
。
withChain
withChain用于指定应该按顺序运行的队列列表。它只是一个语法糖,实际上的效果等同于:
// 1. withChain的用法
Job::withChain([
new OptimizePodcast,
new ReleasePodcast
])->dispatch();
// 2. 等同于dispatch的用法
Job::dispatch()->chain([
new OptimizePodcast,
new ReleasePodcast
])
2.1.2 IlluminateBusQueueable
上文提到的PendingDispath
,可以指定队列信息的方法,都是转发到任务对应的方法进行调用,Queueable就是实现了这部分的功能。这部分包括以下接口:
|方法名|描述| |---|---| |onConnection|指定连接名 | |onQueue| 指定队列名 | |allOnConnection| 指定工作链的连接名 | |allOnQueue| 指定工作链的队列名 | |delay| 设置延迟执行时间 | |chain| 指定工作链 |
以及最后一个方法dispatchNextJobInChain
。上述方法都是在任务执行前调用,设置任务相关参数。dispatchNextJobInChain
是在任务执行期间,如果检查到任务定义了工作链,就会派发工作链上面的任务到队列中。
2.1.3 IlluminateQueueSerializesModels
这个trait的作用是字符串化任务信息,方便将任务信息保存到数据库或Redis等存储器中,然后在队列的消费端取出任务信息,并据此重新实例化为任务对象,便于执行任务。
2.1.4 IlluminateQueueInteractsWithQueue
这个trait赋予了任务与队列进行数据交互的能力。InteractsWithQueue是任务的必要组成,如果一个任务只能被执行,而不能与队列进行交互,那么这个任务在队列中的状态就是未知的,必然会造成混乱。InteractsWithQueue与队列的交互能力来源于$job属性,它是一个QueueJob实例,需要与任务的概念进行区别:任务是泛指可执行的对象,而这个$job,是在任务出队以后,解析出来的QueueJob对象。
即时一个任务类实现了InteractsWithQueue,它在实例化的时候并没有$job这个属性。需要等到出队后的执行过程中,这个$job才被手动设置给任务。