簡(jiǎn)介
Horizon 為 Laravel 提供了基于 Redis 的、擁有美觀后臺(tái)的羡疗、代碼驅(qū)動(dòng)配置的隊(duì)列系統(tǒng)染服。Horizon 讓我們可以輕松監(jiān)控隊(duì)列系統(tǒng)的關(guān)鍵指標(biāo),例如任務(wù)吞吐量叨恨、運(yùn)行時(shí)間和失敗任務(wù)等柳刮。
所有的隊(duì)列進(jìn)程配置都存放在一個(gè)單獨(dú)的簡(jiǎn)單配置文件中,這樣的話(huà)配置文件就可以存放到源碼控制以便團(tuán)隊(duì)所有成員的協(xié)作痒钝。
安裝
注:由于 Horizon 使用了異步進(jìn)程信號(hào)秉颗,所以 PHP 7.1+ 以上版本才可以使用。
composer安裝Horizon命令:
composer require laravel/horizon
安裝完成后送矩,使用 Artisan 命令 vendor:publish 發(fā)布前端資源:
php artisan vendor:publish --provider="Laravel\Horizon\HorizonServiceProvider"
配置
發(fā)布好前端資源后蚕甥,主配置文件就會(huì)出現(xiàn)在 config/horizon.php。在這個(gè)配置文件中益愈,你可以配置隊(duì)列進(jìn)程選項(xiàng)以及每個(gè)包含目的描述的配置項(xiàng)梢灭,使用 Horizon 前可瀏覽下這個(gè)配置文件。
balance 配置項(xiàng)
Horizon 提供了三種負(fù)載均衡策略以供選擇:simple蒸其、auto 和 false敏释,simple 是默認(rèn)策略,在進(jìn)程之間平均分配進(jìn)入任務(wù):
'balance' => 'simple',
auto 策略基于隊(duì)列當(dāng)前負(fù)載調(diào)整每個(gè)隊(duì)列的工作進(jìn)程數(shù)量摸袁。例如钥顽,如果 notifications 隊(duì)列有 1000 個(gè)等待執(zhí)行的任務(wù)而 render 隊(duì)列是空的,那么 Horizon 將會(huì)為 notifications 隊(duì)列分配更多的工作進(jìn)程直到隊(duì)列為空靠汁。
如果把 balance 選項(xiàng)設(shè)置為 false蜂大,就會(huì)使用默認(rèn)的 Laravel 行為,也就是按照配置文件中的排列順序處理隊(duì)列蝶怔。
后臺(tái)認(rèn)證
我們可以通過(guò) /horizon 訪問(wèn) Horizon 后臺(tái):
默認(rèn)情況下奶浦,你只能在
local
環(huán)境下訪問(wèn)這個(gè)后臺(tái)。如果想要為后臺(tái)定義更多的特定訪問(wèn)策略踢星,需要使用 Horizon:auth
方法澳叉。auth
方法接收一個(gè)返回true
或 false
的回調(diào),從而決定用戶(hù)是否可以訪問(wèn) Horizon
后臺(tái)。通常成洗,我們會(huì)在 AppServiceProvider
的 boot
方法中調(diào)用 Horizon:auth
:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Laravel\Horizon\Horizon;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
//用戶(hù)是否可以訪問(wèn) Horizon 后臺(tái)
Horizon::auth(function ($request) {
// return true / false;
});
}
}
運(yùn)行 Horizon
如果你已經(jīng)在配置文件 config/horizon.php
中配置過(guò)工作進(jìn)程五督,就可以使用 Artisan
命令 horizon
來(lái)啟動(dòng) Horizon
,該命令會(huì)啟動(dòng)所有配置的工作進(jìn)程:
php artisan horizon
使用 Artisan
命令 horizon:pause
和 horizon:continue
來(lái)暫推垦辏或繼續(xù)處理隊(duì)列任務(wù):
php artisan horizon:pause
php artisan horizon:continue
還可以使用 Artisan
命令 horizon:terminate
來(lái)優(yōu)雅地終止 Horizon
主進(jìn)程 —— Horizon
會(huì)在所有當(dāng)前正在執(zhí)行的任務(wù)全部完成后退出:
php artisan horizon:terminate
部署 Horizon
如果要將 Horizon
部署到線上服務(wù)器充包,需要配置一個(gè)進(jìn)程監(jiān)控來(lái)監(jiān)控 php artisan horizon
命令的運(yùn)行并在異常退出的情況下重啟該進(jìn)程。部署新代碼到服務(wù)器的時(shí)候遥椿,需要終止 Horizon
主進(jìn)程以便通過(guò)配置的進(jìn)程監(jiān)控以最新代碼重啟進(jìn)程基矮。如上所述,我們可以通過(guò) Artisan
命令 horizon:terminate
優(yōu)雅地終止 Horizon
主進(jìn)修壕。
Supervisor
配置
如果你在使用 Supervisor
進(jìn)程監(jiān)控來(lái)管理 horizon
進(jìn)程愈捅,配置例子(按照自己的實(shí)際情況修改相應(yīng)的目錄信息):
[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
注:也可以考慮使用 Laravel Forge,
Forge
提供了PHP 7+
版本的服務(wù)器慈鸠,并且擁有運(yùn)行最新版Laravel
應(yīng)用所需的所有軟件工具集。
標(biāo)簽
Horizon
允許分配"標(biāo)簽"到任務(wù)灌具,包括郵件青团、事件廣播、通知以及隊(duì)列事件監(jiān)聽(tīng)器等咖楣。實(shí)際上督笆,Horizon
會(huì)基于附加到任務(wù)的 Eloquent
模型為大部分任務(wù)以智能的方式自動(dòng)打上標(biāo)簽。例如诱贿,我們來(lái)看看下面這個(gè)例子:
<?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;
/**
* The video instance.
*
* @var \App\Video
*/
public $video;
/**
* Create a new job instance.
*
* @param \App\Video $video
* @return void
*/
public function __construct(Video $video)
{
$this->video = $video;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
//
}
}
如果任務(wù)被推送到隊(duì)列時(shí)附帶了一個(gè) id
為 1
的 App\Video
實(shí)例娃肿,它將會(huì)自動(dòng)打上 App\Video:1
的標(biāo)簽,這是因?yàn)?Horizon
會(huì)檢查隊(duì)列任務(wù)屬性中的 Eloquent
模型珠十,如果 Eloquent
模型被找到料扰,Horizon
就會(huì)使用模型類(lèi)名和主鍵為任務(wù)智能地打上標(biāo)簽:
$video = App\Video::find(1);
App\Jobs\RenderVideo::dispatch($video);
手動(dòng)打標(biāo)簽
如果你想要手動(dòng)定義某個(gè)隊(duì)列對(duì)象的標(biāo)簽,可以在該類(lèi)中定義一個(gè) tags
方法:
class RenderVideo implements ShouldQueue
{
/**
* Get the tags that should be assigned to the job.
*
* @return array
*/
public function tags()
{
return ['render', 'video:'.$this->video->id];
}
}
通知
注:在使用通知之前焙蹭,需要通過(guò)
Composer
安裝guzzlehttp/guzzle
依賴(lài)晒杈。在配置Horizon
發(fā)送短信通知前,還要回顧下 Nexmo 通知驅(qū)動(dòng)的預(yù)備知識(shí)孔厉。
如果你想要在某個(gè)隊(duì)列任務(wù)等待很長(zhǎng)時(shí)間后被通知拯钻,可以使用 Horizon::routeMailNotificationsTo
、Horizon::routeSlackNotificationsTo
以及 Horizon::routeSmsNotificationsTo
方法撰豺。你可以在 AppServiceProvider
中調(diào)用這些方法:
Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
Horizon::routeSmsNotificationsTo('15556667777');
配置通知等待時(shí)間下限
你可以在配置文件 config/horizon.php
中通過(guò)修改 waits
配置項(xiàng)來(lái)配置每個(gè)連接/隊(duì)列上的等待時(shí)間下限(秒):
'waits' => [
'redis:default' => 60,
],
監(jiān)控
Horizon
提供了一個(gè)監(jiān)控后臺(tái)查看任務(wù)和隊(duì)列的等待時(shí)間和吞吐量信息粪般,為了獲取實(shí)時(shí)信息,可以配置 Horizon
的 Artisan
命令 snapshot
通過(guò)應(yīng)用的調(diào)度器每五分鐘運(yùn)行一次:
/**
* Define the application's command schedule.
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule)
{
$schedule->command('horizon:snapshot')->everyFiveMinutes();
}