QueueServiceProvider
Laravel Most registrations of various services are bound through various ServiceProviders, and queue services are no exception. Open the namespace IlluminateQueueQueueServiceProvider file and locate the register method.
public function register() { // 注册队列管理器 一旦实例化,为队列连接器注册各种解析器,这些连接器负责创建接受队列配置和实例化各种不同队列处理的类。 // 按照配置文件注册一个默认连接方式 在此使用 redis $this->registerManager(); // 注册队列各种命令 队列连接 重启等。 $this->registerWorker(); // 注册队列监听命令 $this->registerListener(); // 5.1后弃用 $this->registerSubscriber(); // 注册队列失败处理 $this->registerFailedJobServices(); // Register the Illuminate queued closure job. 什么用,后面再看。 $this->registerQueueClosure(); }
Task creation and allocation
php artisan make:job SendReminderEmail
Follow the documentation This method generates a queue task class, which inherits namespaceAppJobsJob and implements the interfaces SelfHandling and ShouldQueue. Maybe you will ask what is the use of these two interfaces without any specification (skip them first). The focus is on the two traits. Various operations, deletion, retry, delay, etc. are implemented for queue tasks.
When allocating tasks, we use the auxiliary function dispatch, which is actually the dispatch method of the Dispatcher class under IlluminateBus
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' ); }
Here, let’s first look at the
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']; // 默认队列连接 }); }); }
Then let’s look at 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); } }
The above task enters the queue The whole process is clear. What about dequeuing tasks? We can see in the document that we monitor the queue by executing the statement php artisan queue:work. Let’s take a look at namespace IlluminateQueueConsoleWorkCommand::fire(). It’s very late at night. Let’s take a look for yourself!