原文链接https://divinglaravel.com/queue-system/pushing-jobs-to-queue推送作业到队列有几种方式:有有几种方法可以将作业推送到队列:Queue::push(newInvoiceEmail($order));Bus::dispatch(newInvoiceEmail($order));dispatch(newInvoiceEmail($order));(newInvoiceEmail($order))->dispatch();正如在之前的潜水中所解释的,对Queuefacade的调用是对您的应用程序使用的队列驱动程序的调用,例如调用push方法是对Queue\DatabaseQueue类,以防您使用数据库队列驱动程序。您可以使用几种有用的方法:调用Queuefacade是对应用程序使用的队列驱动程序的调用。如果使用数据库队列驱动,调用push方法就是调用Queue\DatabaseQueue类的push方法。可以使用几种有用的方法://将作业推送到特定队列Queue::pushOn('emails',newInvoiceEmail($order));//在给定秒数后推送作业Queue::later(60,newInvoiceEmail($order));//在延迟后将作业推送到特定队列Queue::laterOn('emails',60,newInvoiceEmail($order));//推送多个作业Queue::bulk([newInvoiceEmail($order),newThankYouEmail($order)]);//推送多个作业到特定队列Queue::bulk([newInvoiceEmail($order),newThankYouEmail($order)],null,'电子邮件');在调用这些方法中的任何一个之后,选定的队列驱动程序会将给定的信息存储在一个存储空间中,供工作人员按需提取。调用这些方法后,选定的队列驱动程序会将给定的信息存储在存储空间中,供工作人员按需提取。信息存储在存储空间中,供工作人员按需获取。使用命令总线使用命令总线将作业分派到队列中,为您提供了额外的控制;您可以在您的作业类中设置选定的连接、队列和延迟,决定命令是否应该排队或立即运行,在运行之前通过管道发送作业,实际上您甚至可以在您的内部处理整个排队过程工作类。Busfacade代理Contracts\Bus\Dispatcher容器别名,这个别名被解析为Bus\BusServiceProvider中的Bus\Dispatcher实例:使用命令总线来安排队列作业给你额外的控制;您可以从作业类中设置选定的连接、队列和延迟,以决定命令是应该排队还是立即运行,在运行之前通过管道发送作业,实际上您甚至可以在作业类中处理整个队列过程.Bugfacade代理到Contracts\Bus\Dispatcher容器别名,这别名解析为Bus\Dispatcher内的Bus\BusServiceProvider的一个实例:$this->app->singleton(Dispatcher::class,function($app){returnnewDispatcher($app,function($connection=null)use($app){return$app[QueueFactoryContract::class]->connection($connection);});});所以Bus::dispatch()调用的dispatch()方法是Bus\Dispatcher类的:publicfunctiondispatch($command){if($this->queueResolver&&$this->commandShouldBeQueued($command)){return$this->dispatchToQueue($command);}else{return$this->dispatchNow($command);}}此方法决定给定的作业是否应该被分派到队列或立即运行,commandShouldBeQueued()方法检查作业类是否是Contracts\Queue\ShouldQueue的实例,因此使用此方法您的作业只会在以下情况下排队你实现ShouldQueue接口。我们不打算在本次潜水中研究dispatchNow,它是当我们深入研究工人如何运行工作时,我会详细讨论。现在让我们看看Bus是如何将你的作业调度到队列中的:这个方法决定是将给定的作业调度到队列中还是立即运行它,commandShouldBeQueued()方法检查作业类是否是Contracts\Queue\的实例ShouldQueue,所以使用这个方法,你的job只有继承了ShouldQueue接口才会被放入队列。本文我们不会深入dispatchNow,我们会深入到worker如何执行详细讨论的job。现在我们来看看总线如何调整你的工作组:publicfunctiondispatchToQueue($command){$connection=isset($command->connection)?$命令->连接:空;$queue=call_user_func($this->queueResolver,$connection);if(!$queueinstanceofQueue){thrownewRuntimeException('队列解析器没有返回队列实现。');}if(method_exists($command,'queue')){return$command->queue($queue,$command);}else{return$this->pushCommandToQueue($queue,$command);}}首先,Laravel检查你的作业类中是否定义了连接属性,使用该属性你可以设置Laravel应该将排队的作业发送到哪个连接,如果没有定义属性,将使用null,在这种情况下,Laravel将使用默认值连接。使用连接值,Laravel使用一个queueResolver闭包来构建应该使用的队列驱动程序的实例,这个闭包在Bus\BusServiceProvide中设置r在注册Dispatcher实例时:首先,Laravel会检查你的作业类中是否定义了connection属性。使用此属性设置Laravel应将排队的作业发送到哪个连接。如果未定义任何属性,则将使用null属性。这里在这种情况下Laravel将使用默认连接通过连接设置,Laravel使用一个queueResolver闭包来构造应该使用哪个队列驱动程序实例。这个闭包是在注册调度器实例时在Bus\BusServiceProvider中设置的:Contracts\Queue\Factory是Queue\QueueManager的别名,所以换句话说,这个闭包返回QueueManager的一个实例,并为管理器设置所需的连接以了解使用哪个驱动程序。最后dispatchToQueue方法检查作业类是否有队列方法,如果是这种情况,调度程序将只调用此方法,让您完全控制作业的排队方式,您可以选择队列、分配延迟、设置最大重试次数,超时等...如果没有找到队列方法,调用pushCommandToQueue()会在所选队列驱动程序上调用正确的推送方法:Contracts\Queue\Factory是Queue\QueueManager的别名,换句话说,这个闭包返回一个QueueManager实例并设置管理器使用的队列驱动程序所需的连接。最后,dispatchToQueue方法检查作业类是否有队列方法。如果调度程序调用此方法,您可以完全控制作业的排队方式。您可以选择队列,分配延迟,设置最大重试次数,超时等。如果没有找到队列方法,则对pushCommandToQueue()的调用将调用所选队列驱动程序上的推送方法:protectedfunctionpushCommandToQueue($queue,$command){if(isset($command->queue,$command->delay)){return$queue->laterOn($command->queue,$command->delay,$command);}if(isset($command->queue)){return$queue->pushOn($command->queue,$command);}if(isset($command->delay)){return$queue->later($command->delay,$command);}return$queue->push($command);}调度程序检查作业类中的队列和延迟属性,并根据它选择合适的队列方法。调度程序检查Job类中的队列和延迟,并根据此选择适当的队列方法。那么我可以在作业类中设置队列、延迟和连接吗?那么我可以在作业类中设置队列、延迟和连接吗?是的,您还可以设置尝试和超时属性,队列驱动程序也将使用这些值,您的作业类可能如下所示:是的,您还可以设置尝试和超时属性,队列驱动程序将使用这些值这些值也是如此,这里是您的作业类可能的样子:值,以下作业类示例:classSendInvoiceEmail{public$connection='default';public$queue='电子邮件';公共$延迟=60;公共$尝试=3;public$timeout=20;}SettingjobconfigurationontheSetjobconfigurationonthefly使用dispatch()globalhelper你可以做这样的事情:dispatch(newInvoiceEmail($order))->onConnection('default')->onQueue('emails')->delay(60);这仅在您在作业类中使用Bus\Queueable特性时有效,该特性包含几种方法,您可以使用这些方法在调度作业类之前设置一些属性,例如:这仅在您在作业类中使用Bus\Queueable特性时才有效,该特性包含几个您可以分配给的方法在调度作业类之前设置作业类的一些属性,例如:publicfunctiononQueue($queue){$this->queue=$queue;return$this;}但是在您的示例中,我们在dispatch()返回时调用方法!但是在你的例子中,我们调用了dispatch()的return方法!技巧如下:functiondispatch($job){returnnewPendingDispatch($job);}这是Foundation/helpers.php中dispatch()助手的定义,它返回Bus\PendingDispatch的一个实例,在这个类中我们有这样的方法:这是Foundation/helpers.php中dispatch()辅助方法的定义,它返回Bus\PendingDispatch的一个实例,在这个类中,我们有这个方法:publicfunctiononQueue($queue){$this->job->onQueue($queue);return$this;}所以当我们做dispatch(newJobClass())->onQueue('default')时,PendingDispatch的onQueue方法会调用job类的onQueue方法,前面我们提到job类需要使用所有这些都可以工作的队列特性。所以当我们执行dispatch(newJobClass())->onQueue('default')时,PendingDispatch的onQueue方法会调用job类在onQueue方法上,如前所述,作业类需要使用所有这些Queueable特性才能工作。那么调用Dispatcher::dispatch方法的部分在哪里呢?那么调用Dispatcher::dispatch方法的部分在哪里呢?一旦你执行了dispatch(newJobClass())->onQueue('default')你就会准备好作业实例,实际的工作发生在PendingDispatch::__destruct()中:一旦你执行了dispatch(newJobClass())->onQueue('default'),您将使作业实例准备好进行调度,实际工作发生在PendingDispatch::__destruct()中:publicfunction__destruct(){app(Dispatcher::class)->dispatch($this->job);}此方法在调用时将从容器中解析一个Dispatcher实例,并对其调用dispatch()方法。__destruct()是一种PHP魔术方法,当对对象的所有引用不再存在或脚本终止时调用该方法,并且由于我们不在任何地方存储对PendingDispatch实例的引用,因此__destruct方法将立即被调用:方法被调用时,会从容器中解析出一个Dispatcher的实例,然后调用dispatch()方法。destruct()是一个PHP魔术方法,当所有对对象的引用不再存在或脚本终止时调用,因为我们不会立即在__destruct方法中存储对PendingDispatch实例的引用,//这里的析构函数将被称为rightawaydispatch(newJobClass())->onQueue('default');//如果我们调用unset($temporaryVariable),那么析构函数将被调用//或在脚本完成执行时调用。$temporaryVariable=dispatch(newJobClass())->onQueue('default');使用Dispatchable特性你可以在你的工作类上使用Bus\Dispatchable特性来像这样调度你的工作:你可以在工作类上使用Bus\Dispatchable特性来调度你的工作,像这样:))->调度();Dispatchable的调度方法如下所示:我们可以这样做:如您所见,它使用了PendingDispatch的一个实例,这意味着我们可以这样做:(newInvoiceEmail($order))->dispatch()->onQueue('emails');转载请注明:转载自Ryan是菜鸟|LNMP技术栈笔记如果觉得这篇文章对你很有帮助,不妨打赏一下本文链接地址:浅析Laravel队列系统--推送作业到队列
