Laravel 队列源码解析(上)

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: Laravel 队列源码解析

开篇


日常开发使用队列的场景不少了吧,至于如何使用,我想文档已经写的很清楚了,毕业一年多了,七月份换一家新公司的时候开始使用 Laravel,因为项目中场景经常使用到 Laravel 中的队列,结合自己阅读的一丝队列的源码,写了这篇文章。(公司一直用的 5.5 所以文章的版本你懂的。)


也不知道从哪讲起,那就从一个最基础的例子开始吧。创建一个最简单的任务类 SendMessage。继承 Illuminate\Contracts\Queue\ShouldQueue 接口。


简单 demo 开始


<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Support\Facades\Log;
class SendMessage implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $message;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($message)
    {
        $this->message = $message;
    }
    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        Log::info($this->message);
    }
}

这里直接分发一个任务类到队列中,并没有指定分发到哪个队列,那么会直接分发给默认的队列。直接从这里开始分析吧。

public function test()
    {
        $msg = '吴亲库里';
        SendMessage::dispatch($msg);
    }

首先 SendMessage 并没有 dispatch 这个静态方法, 但是它 use dispatchable 这样的 Trait 类,我们可以点开 dispatchable 类查看 dispatch 方法。

trait Dispatchable
{
    /**
     * Dispatch the job with the given arguments.
     *
     * @return \Illuminate\Foundation\Bus\PendingDispatch
     */
    public static function dispatch()
{
        return new PendingDispatch(new static(...func_get_args()));
    }
    /**
     * Set the jobs that should run if this job is successful.
     *
     * @param  array  $chain
     * @return \Illuminate\Foundation\Bus\PendingChain
     */
    public static function withChain($chain)
{
        return new PendingChain(get_called_class(), $chain);
    }
}

可以看到在 dispatch 方法中 实例化另一个 PendingDispatch 类,并且根据传入的参数实例化任务 SendMessage 作为 PendingDispatch 类的参数。我们接着看,它是咋么分派任务?外层控制器现在只调用了 dispatch, 看看 PendingDispatch 类中有什么

<?php
namespace Illuminate\Foundation\Bus;
use Illuminate\Contracts\Bus\Dispatcher;
use Illuminate\Support\Facades\Log;
class PendingDispatch
{
    /**
     * The job.
     *
     * @var mixed
     */
    protected $job;
    /**
     * Create a new pending job dispatch.
     *
     * @param  mixed  $job
     * @return void
     */
    public function __construct($job)
{
        $this->job = $job;
    }
    /**
     * Set the desired connection for the job.
     *
     * @param  string|null  $connection
     * @return $this
     */
    public function onConnection($connection)
{
        $this->job->onConnection($connection);
        return $this;
    }
    /**
     * Set the desired queue for the job.
     *
     * @param  string|null  $queue
     * @return $this
     */
    public function onQueue($queue)
{
        $this->job->onQueue($queue);
        return $this;
    }
    /**
     * Set the desired connection for the chain.
     *
     * @param  string|null  $connection
     * @return $this
     */
    public function allOnConnection($connection)
{
        $this->job->allOnConnection($connection);
        return $this;
    }
    /**
     * Set the desired queue for the chain.
     *
     * @param  string|null  $queue
     * @return $this
     */
    public function allOnQueue($queue)
{
        $this->job->allOnQueue($queue);
        return $this;
    }
    /**
     * Set the desired delay for the job.
     *
     * @param  \DateTime|int|null  $delay
     * @return $this
     */
    public function delay($delay)
{
        $this->job->delay($delay);
        return $this;
    }
    /**
     * Set the jobs that should run if this job is successful.
     *
     * @param  array  $chain
     * @return $this
     */
    public function chain($chain)
{
        $this->job->chain($chain);
        return $this;
    }
    /**
     * Handle the object's destruction.
     *
     * @return void
     */
    public function __destruct()
{
        app(Dispatcher::class)->dispatch($this->job);
    }
}

这里查看它的构造和析构函数。好吧从析构函数上已经能看出来,执行推送任务的在这里,app(Dispatcher::class) 这又是什么鬼?看来还得从运行机制开始看。Laravel 底层提供了一个强大的 IOC 容器,我们这里通过辅助函数 app() 的形式访问它,并通过传递参数解析出一个服务对象。这里我们传递 Dispatcher::class 得到的是一个什么服务?这个服务又是在哪里被注册进去的。让我们把目光又转移到根目录下的 index.php 文件。因为这篇文章不是说运行流程,所以一些流程会跳过。


注册服务

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

这个服务实际上执行了 handle 方法之后才有的 (别问我为什么,如果和我一样笨的话,多打断点😂), 这里的 $kernel 实际上得到的是一个 Illuminate\Foundation\Http\Kernel 类,让我们进去看看这个类里面的 handle 方法。

/**
     * Handle an incoming HTTP request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function handle($request)
  {
        try {
            $request->enableHttpMethodParameterOverride();
            $response = $this->sendRequestThroughRouter($request);
        } catch (Exception $e) {
            $this->reportException($e);
            $response = $this->renderException($request, $e);
        } catch (Throwable $e) {
            $this->reportException($e = new FatalThrowableError($e));
            $response = $this->renderException($request, $e);
        }
        $this->app['events']->dispatch(
            new Events\RequestHandled($request, $response)
        );
        return $response;
    }
相关文章
|
13天前
|
监控 网络协议 Java
Tomcat源码解析】整体架构组成及核心组件
Tomcat,原名Catalina,是一款优雅轻盈的Web服务器,自4.x版本起扩展了JSP、EL等功能,超越了单纯的Servlet容器范畴。Servlet是Sun公司为Java编程Web应用制定的规范,Tomcat作为Servlet容器,负责构建Request与Response对象,并执行业务逻辑。
Tomcat源码解析】整体架构组成及核心组件
|
1天前
|
开发工具
Flutter-AnimatedWidget组件源码解析
Flutter-AnimatedWidget组件源码解析
|
20天前
|
测试技术 Python
python自动化测试中装饰器@ddt与@data源码深入解析
综上所述,使用 `@ddt`和 `@data`可以大大简化写作测试用例的过程,让我们能专注于测试逻辑的本身,而无需编写重复的测试方法。通过讲解了 `@ddt`和 `@data`源码的关键部分,我们可以更深入地理解其背后的工作原理。
18 1
|
30天前
|
开发者 Python
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
61 1
|
11天前
|
缓存 PHP 开发者
Laravel 模板引擎深度解析
【8月更文挑战第31天】
17 0
|
11天前
|
测试技术 PHP 开发工具
深入解析 Laravel 中的 Composer Lock 文件
【8月更文挑战第31天】
7 0
|
11天前
|
测试技术 PHP 开发工具
深入解析 Laravel 中的 Composer Lock 文件
【8月更文挑战第31天】
11 0
|
26天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
1月前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
52 6
|
30天前
|
开发者 Python
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
深入解析Python `requests`库源码,揭开HTTP请求的神秘面纱!
108 1

热门文章

最新文章

推荐镜像

更多