【Laravel-海賊王系列】第十九章, 精通 Horizon 以後能夠隨心所欲(上)

前言

HorizonLaravel 做者對框架 Queue 的一個補充包,功能強大,使用簡單,本章將解析 Horizon 的是如何啓動的php


啓動

`php artisan horizon`

那麼熟悉的命令,一會兒就點亮世界。
複製代碼

完整結構

Horizon 在 Redis 中的完整結構 , 後面解釋字段含義。json

源碼解析

開始進入源碼部分了,請坐穩扶好, 這是咱們啓動 Horizon 的時候觸發的代碼,標註了 6 處帶分析的地方bash

public function handle(MasterSupervisorRepository $masters)
{
    if ($masters->find(MasterSupervisor::name())) {
        return $this->comment('A master supervisor is already running on this machine.');
    }  1️⃣ 

    $master = (new MasterSupervisor)->handleOutputUsing(function ($type, $line) {
        $this->output->write($line);
    }); 2️⃣

    ProvisioningPlan::get(MasterSupervisor::name())->deploy(
        $this->option('environment') ?? config('horizon.env') ?? config('app.env')
    ); 3️⃣

    $this->info('Horizon started successfully.');

    pcntl_async_signals(true); 4️⃣

    pcntl_signal(SIGINT, function () use ($master) {
        $this->line('Shutting down...');

        return $master->terminate();
    }); 5️⃣

    $master->monitor(); 6️⃣
}
複製代碼

6 塊代碼分析

  • 1️⃣ 這裏就是生成一個 gethostname() + Str::random(4)Master 進程名稱,若是不幸產生了同名的進程,那麼直接返回一個錯誤提醒~

  • 2️⃣初始化 MasterSupervisor 對象php7

    $this->name 在第一步就已經生成了靜態的名字了app

    $this->supervisors 能夠看出給了一個集合,一看就是要支持多個進程的樣子框架

    $this->output 第二步就是讓 output 屬性能擁有輸出到緩衝區的能力dom

    最後一步是刷新,刷新高清大圖中的 horizon:master:gethostname()+Str::random(4) 這個進程名稱異步

    關於這個 flush 方法幹了啥你們必定很好奇 $this->connection()->del('commands:'.$name);async

    這就是它作的事情,去 Redis 刪除這個 key。函數


  • 3️⃣過了四級的我翻譯了一下:

    建立一個資源分配計劃!

    這個就是 Horizon 的配置文件,裏面的 processes 進程數,balance 進程分配策略等等各項參數

    就是經過這個 ProvisioningPlan 類解析的內容。

    🏁這裏咱們解析一下它對應的方法

    ProvisioningPlan::get(MasterSupervisor::name())
    這時候至關於獲得了一個具備指定配置文件和進程 `Name` 的對象。
    複製代碼

    接着

    (new ProvisioningPlan)->deploy(
        $this->option('environment') ?? config('horizon.env') ?? config('app.env')
    ); 
    複製代碼

    部署指定環境的配置,這段代碼目的是將全部後面要執行的指令先 rpushRedis 中。

    實際就是執行下圖方法,將參數存到 Redis

    上圖中的代碼不會當即建立這些數據,而是暫存了相關建立指令到 Redis

    存到Redis的格式是,變量表明本機名稱: 'commands:master:gethostname()+Str::random(4)': json_encode([AddSupervisor::class,$options])

    $options 如圖

    這樣理解,就是把操做和配置存到 Redis,後面要執行的時候就能夠查出全部相關的數據生成對應的進程!

    🏁動手確認

    執行 php artisan horizon 去看看 Redis 中的變化

    要不是這個 dd() 這個數據立馬就被消費了!

    咱們此時能夠大膽猜測下圖中就是後續要建立的進程!

    這時候你們確定有疑問了,接下來 Horizon 將會在何時消費掉 Redis 中的數據,而後生成對應的 進程呢。這個就要繼續日後看了!


  • 4️⃣這裏沒什麼好講的,在php7.1以後,有了新的信號處理函數:pcntl_async_signals,返回或設置是否異步信號處理。


  • 5️⃣這裏註冊一個 terminate的信號,功能是關閉進程。好比咱們在 Mac OsCommand + C的時候就是發送這個信號。咱們先大概看一下,是如何關閉全部進程的,具體實現放到後面的篇幅講。


  • 6️⃣好了,到了本章最核心的部分了,先看核心方法

    $this->ensureNoOtherMasterSupervisors(),確保是否存在相同名字的進程,若是有,就拋出異常。

    $this->listenForSignals(),註冊將要處理的信號

    $this->persist()RedisCommands 下的 key 更新到 Master 下面。

    接着執行 $this->loop(), 啓動進程。

    這裏咱們關注 $this->monitorSupervisors() 調用。

    這裏的類是 Laravel\Horizon\SupervisorProcess ,別問我怎麼知道的!dd() 出來看到的~~,其實要分析就要回到前面去看,初始化那部分了。

    最後

    這裏就是控制啓動進程相關的代碼了,其實 $this->process 也是使用了 Symfony\Component\Process這個老大哥包裏面的功能,畢竟它已經完整的實現了進程管理。英文好的鐵汁自行解讀其中內容。

    打印

    經歷過上面的階段,咱們打印一下本機的進程


結束

關於前面那個管理實例的初始化部分有些略過,

你們能夠這樣理解,就是經過各類方式將要啓動的進程相關數據保存到 MasterSupervisor 對象中,在最後根據對象中的數據建立進程。

本章總算結束了,php artisan horizon 如此而已。

相關文章
相關標籤/搜索