Horizon
是 Laravel
做者對框架 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️⃣
}
複製代碼
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')
);
複製代碼
部署指定環境的配置,這段代碼目的是將全部後面要執行的指令先 rpush
到 Redis
中。
實際就是執行下圖方法,將參數存到 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 Os
按 Command + C
的時候就是發送這個信號。咱們先大概看一下,是如何關閉全部進程的,具體實現放到後面的篇幅講。
6️⃣好了,到了本章最核心的部分了,先看核心方法
$this->ensureNoOtherMasterSupervisors()
,確保是否存在相同名字的進程,若是有,就拋出異常。
$this->listenForSignals()
,註冊將要處理的信號
$this->persist()
將 Redis
中 Commands
下的 key
更新到 Master
下面。
接着執行 $this->loop()
, 啓動進程。
這裏咱們關注 $this->monitorSupervisors()
調用。
這裏的類是 Laravel\Horizon\SupervisorProcess
,別問我怎麼知道的!dd()
出來看到的~~,其實要分析就要回到前面去看,初始化那部分了。
最後
這裏就是控制啓動進程相關的代碼了,其實 $this->process
也是使用了 Symfony\Component\Process
這個老大哥包裏面的功能,畢竟它已經完整的實現了進程管理。英文好的鐵汁自行解讀其中內容。
打印
經歷過上面的階段,咱們打印一下本機的進程
關於前面那個管理實例的初始化部分有些略過,
你們能夠這樣理解,就是經過各類方式將要啓動的進程相關數據保存到 MasterSupervisor
對象中,在最後根據對象中的數據建立進程。
本章總算結束了,php artisan horizon
如此而已。