Horizon 隊(duì)列管理工具
Horizon 隊(duì)列管理工具
Laravel Horizon
介紹
Horizon 提供了一個(gè)漂亮的儀表盤,并且可以通過(guò)代碼配置你的 Laravel Redis 隊(duì)列,同時(shí)它允許你輕易的監(jiān)控你的隊(duì)列系統(tǒng)中諸如任務(wù)吞吐量,運(yùn)行時(shí)間和失敗任務(wù)等關(guān)鍵指標(biāo)。
所有的配置項(xiàng)都存放在一個(gè)簡(jiǎn)單的配置文件中,從而允許你將它放在團(tuán)隊(duì)的協(xié)同版本控制中,方便團(tuán)隊(duì)協(xié)作。
安裝
{note} 你應(yīng)該確保
queue
配置文件中設(shè)置了redis
隊(duì)列驅(qū)動(dòng)。
你應(yīng)該使用 Composer 來(lái)安為你的 Laravel 項(xiàng)目安裝 Horizon:
composer require laravel/horizon
安裝完成后,使用 horizon:install
發(fā)布 Artisan 命令:
php artisan horizon:install
你還應(yīng)該創(chuàng)建 failed_jobs
表,Laravel 將使用該表來(lái)存儲(chǔ)任何 失敗的隊(duì)列任務(wù):
php artisan queue:failed-table php artisan migrate
配置
發(fā)布 Horizon 相關(guān)文件后,他的主要配置文件會(huì)放在 config/horizon.php
。你可以在這個(gè)文件中配置隊(duì)列相關(guān)選項(xiàng),并且每個(gè)配置項(xiàng)都有詳細(xì)的使用說(shuō)明,請(qǐng)?jiān)敿?xì)閱讀此文件。
均衡配置
Horizon 提供了三種均衡策略:simple
,auto
, 和 false
。默認(rèn)的是 simple
, 會(huì)將收到的任務(wù)均分給隊(duì)列進(jìn)程:
'balance' => 'simple',
auto
策略會(huì)根據(jù)當(dāng)前的工作量調(diào)整每個(gè)隊(duì)列的工作進(jìn)程任務(wù)數(shù)量。例如:如果 notifications
隊(duì)列有 1000 個(gè)待執(zhí)行任務(wù),但是你的 render
隊(duì)列是空的,Horizon 會(huì)分配更多的工作進(jìn)程給 notifications
隊(duì)列,直到 notifications
隊(duì)列中所有任務(wù)執(zhí)行完成。當(dāng)配置項(xiàng) balance
配置為 false
時(shí),Horizon 會(huì)使用 Laravel 默認(rèn)執(zhí)行行為,它將按照配置中列出的順序處理隊(duì)列任務(wù)。
任務(wù)修整
horizon
配置文件允許你配置應(yīng)保留最近和失敗任務(wù)的時(shí)間(以分鐘為單位)。 默認(rèn)情況下,最近的任務(wù)保留一小時(shí),而失敗的任務(wù)保留一周:
'trim' => [ 'recent' => 60, 'failed' => 10080, ],
儀表盤權(quán)限驗(yàn)證
Horizon 儀表盤路由是 /horizon
。 默認(rèn)情況下,你只能在 local
環(huán)境下訪問(wèn)儀表盤。在你的 app/Providers/HorizonServiceProvider.php
文件中,有一個(gè) gate
方法。這里授權(quán)控制 非本地 環(huán)境中對(duì) Horizon 的訪問(wèn)。 你可以根據(jù)需要隨意修改此門面,以限制對(duì) Horizon 安裝的訪問(wèn):
/** * 注冊(cè) Horizon gate 方法 * * gate 決定了誰(shuí)可以在非本地環(huán)境中訪問(wèn) Horizon。 * * @return void */ protected function gate(){ Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ 'taylor@laravel.com', ]); }); }
運(yùn)行 Horizon
當(dāng)在 config/horizon.php
文件中配置好了你的隊(duì)列執(zhí)行進(jìn)程后,你就可以使用 horizon
Artisan 命令啟動(dòng) Horizon。只需要一條命令語(yǔ)句即可啟動(dòng)所有配置好的隊(duì)列進(jìn)程:
php artisan horizon
你也可以使用 horizon:pause
和 horizon:continue
Artisan 命令來(lái)暫停或繼續(xù)執(zhí)行隊(duì)列任務(wù):
php artisan horizon:pausephp artisan horizon:continue
你可以使用 horizon:terminate
Artisan 命令優(yōu)雅的終止 Horizon 主進(jìn)程。Horizon 會(huì)把正在執(zhí)行的任務(wù)處理完畢后退出:
php artisan horizon:terminate
部署 Horizon
如果你將 Horizon 部署到線上服務(wù)器時(shí),則需要配置一個(gè)進(jìn)程監(jiān)控器來(lái)檢測(cè) php artisan horizon
命令,在它意外退出時(shí)自動(dòng)重啟。上線新代碼時(shí)則需要該進(jìn)程監(jiān)控器終止 Horizon 進(jìn)程并以修改后的代碼重啟 Horizon。
Supervisor 配置
如果你使用 Supervisor 進(jìn)程監(jiān)控器管理你的 horizon
進(jìn)程,那么以下配置文件則可滿足需求:
[program:horizon] process_name=%(program_name)s command=php /home/forge/app.com/artisan horizon autostart=true autorestart=true user=forge redirect_stderr=true stdout_logfile=/home/forge/app.com/horizon.log
{tip} 如果你不喜歡自己維護(hù)服務(wù)器,可以考慮使用 Laravel Forge,F(xiàn)orge 提供了運(yùn)行一個(gè)帶有 Horizon 的現(xiàn)代、強(qiáng)大的 Laravel 應(yīng)用所需要的 PHP7+ 及其他所有環(huán)境。
標(biāo)簽
Horizon 允許你對(duì)任務(wù)分配「標(biāo)簽」,包括郵件,事件廣播,通知和隊(duì)列的事件監(jiān)聽器。事實(shí)上,Horizon 會(huì)智能并且自動(dòng)根據(jù)任務(wù)攜帶 Eloquent 模型給大多數(shù)任務(wù)標(biāo)記標(biāo)簽,如下任務(wù)示例:
<?php namespace App\Jobs; use App\Video;use Illuminate\Bus\Queueable; use Illuminate\Queue\SerializesModels; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Bus\Dispatchable; class RenderVideo implements ShouldQueue{ use Dispatchable, InteractsWithQueue, Queueable, SerializesModels; /** * video 實(shí)例 * * @var \App\Video */ public $video; /** * 創(chuàng)建工作實(shí)例 * * @param \App\Video $video * @return void */ public function __construct(Video $video) { $this->video = $video; } /** * 執(zhí)行任務(wù) * * @return void */ public function handle() { // } }
如果該隊(duì)列任務(wù)是一個(gè)攜帶 id
為 1
的 App\Video
實(shí)例,那么它將自動(dòng)被標(biāo)記上 App\Video:1
標(biāo)簽。因?yàn)?Horizon 會(huì)檢查任務(wù)屬性是否具有 Eloquent 模型,如果發(fā)現(xiàn) Eloquent 模型,Horizon 將會(huì)智能的用該模型的類名和主鍵為任務(wù)標(biāo)記上標(biāo)簽:
$video = App\Video::find(1); App\Jobs\RenderVideo::dispatch($video);
自定義標(biāo)簽
如果你想手動(dòng)的為隊(duì)列執(zhí)行的對(duì)象定義標(biāo)簽,你可以給這個(gè)類定義一個(gè) tags
方法:
class RenderVideo implements ShouldQueue{ /** * 獲取分配給這個(gè)任務(wù)的標(biāo)簽 * * @return array */ public function tags() { return ['render', 'video:'.$this->video->id]; } }
通知
Note: 在使用通知之前,你應(yīng)該添加
guzzlehttp/guzzle
Composer 包到你的項(xiàng)目。 在使用 Horizon 配置發(fā)送短信通知時(shí),你還應(yīng)該閱讀 Nexmo 通知驅(qū)動(dòng)的依賴條件章節(jié)。
如果需要在隊(duì)列等待時(shí)間過(guò)長(zhǎng)時(shí)發(fā)起通知,可以在應(yīng)用的 AppServiceProvider
中調(diào)用 Horizon::routeMailNotificationsTo
, Horizon::routeSlackNotificationsTo
, 和 Horizon::routeSmsNotificationsTo
方法:
Horizon::routeMailNotificationsTo('example@example.com'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel'); Horizon::routeSmsNotificationsTo('15556667777');
配置等待時(shí)間過(guò)長(zhǎng)的閾值
你可以在 config/horizon.php
配置文件中設(shè)置等待時(shí)間過(guò)長(zhǎng)的具體秒數(shù)。waits
配置項(xiàng)可以針對(duì)每一個(gè) 鏈接 / 隊(duì)列 配置閾值:
'waits' => [ 'redis:default' => 60, ],
Metrics
Horizon 包含一個(gè) Metrics 儀表盤,它可以提供任務(wù)和隊(duì)列等待時(shí)間和吞吐量信息,為了填充此儀表盤,你需要配置應(yīng)用的 scheduler 每五分鐘運(yùn)行一次 Horizon 的 snapshot
Artisan 命令:
/** * 定義應(yīng)用程序的任務(wù)調(diào)度 * * @param \Illuminate\Console\Scheduling\Schedule $schedule * @return void */ protected function schedule(Schedule $schedule){ $schedule->command('horizon:snapshot')->everyFiveMinutes(); }