QueueServiceProvider
Laravel 各種服務的註冊大多都是通過各種 ServiceProvider 進行綁定的,佇列服務也不例外,開啟 namespace IlluminateQueueQueueServiceProvider 檔案定位到 register 方法,
public function register(){ // 註冊隊列管理器 一旦執行個體化,為隊列連接器註冊各種解析器,這些連接器負責建立接受隊列配置和執行個體化各種不同隊列處理的類。 // 按照設定檔註冊一個預設串連方式 在此使用 redis $this->registerManager(); // 註冊隊列各種命令 隊列串連 重啟等。 $this->registerWorker(); // 註冊隊列監聽命令 $this->registerListener(); // 5.1後棄用 $this->registerSubscriber(); // 註冊隊列失敗處理 $this->registerFailedJobServices(); // Register the Illuminate queued closure job. 什麼用,後面再看。 $this->registerQueueClosure();}
任務建立與分配
php artisan make:job SendReminderEmail
按照文檔的方式產生了一個隊列任務類,該類繼承了 namespaceAppJobsJob, 實現了介面 SelfHandling 和 ShouldQueue , 或許你會問這兩個介面啥規範都沒規定啥用啊(先略過), 重點在兩個 trait 內,對隊列任務實現了各種操作,刪除,重試,延遲等。
在分配任務的時候我們使用了輔助函數 dispatch ,其實是 IlluminateBus 下 Dispatcher 類的 dispatch方法
public function dispatch($command, Closure $afterResolving = null){ if ($this->queueResolver && $this->commandShouldBeQueued($command)) { // 隊列執行 return $this->dispatchToQueue($command); } else { // 立即執行 return $this->dispatchNow($command, $afterResolving); }}protected function commandShouldBeQueued($command){ if ($command instanceof ShouldQueue) { // 就這用。。 return true; } return (new ReflectionClass($this->getHandlerClass($command)))->implementsInterface( 'Illuminate\Contracts\Queue\ShouldQueue' );}
在此,我們先看下 namespace IlluminateBusBusServiceProvider 下的
public function register(){ $this->app->singleton('Illuminate\Bus\Dispatcher', function ($app) { return new Dispatcher($app, function () use ($app) { // 'queue.connection' => 'Illuminate\Contracts\Queue\Queue', 再回看 QueueServiceProvider 的 registerManager 方法,就很清晰了。 return $app['Illuminate\Contracts\Queue\Queue']; // 預設隊列串連 }); });}
下面看 dispatchToQueue
public function dispatchToQueue($command){ $queue = call_user_func($this->queueResolver); // 在此為設定的預設值 將執行個體化 RedisQueue // 異常則拋出! if (! $queue instanceof Queue) { throw new RuntimeException('Queue resolver did not return a Queue implementation.'); } if (method_exists($command, 'queue')) { // 可以自訂 return $command->queue($queue, $command); } else { // 在此使用的是進入隊列方式 最終結果類似 $queue->push(); 看 RedisQueue 下的 push 方法。 return $this->pushCommandToQueue($queue, $command); }}
上面任務進入隊列的整個流程就明白了。那任務出隊列呢?在文檔中我們可以看到,我們通過執行 php artisan queue:work 這條語句進行隊列的監聽,那在此就看下 namespace IlluminateQueueConsoleWorkCommand::fire(),夜很深了,下面自己看吧!