Horizon 佇列管理工具
Laravel Horizon
安裝
{note} 你應該確保
queue
設定檔中設定了redis
隊列驅動。
你應該使用Composer 來安為你的Laravel 專案安裝Horizon:
composer require laravel/horizon
安裝完成後,使用horizon:install
發布Artisan 指令:
php artisan horizon:install
你也應該建立failed_jobs
表,Laravel 將使用該表來儲存任何失敗的佇列任務:
php artisan queue:failed-table php artisan migrate
配置
發布Horizon 相關檔案後,他的主要設定檔會放在config/horizon.php
。你可以在這個檔案中設定佇列相關選項,每個設定項都有詳細的使用說明,請詳細閱讀此檔案。
均衡配置
Horizon 提供了三種均衡策略:simple
,auto
, 和 false
。預設的是simple
, 會將收到的任務均分給佇列進程:
'balance' => 'simple',
auto
策略會根據目前的工作量調整每個佇列的工作進程任務數量。例如:如果notifications
佇列有1000 個待執行任務,但是你的render
佇列是空的,Horizon 會指派更多的工作程序給notifications
佇列,直到notifications
佇列中所有任務執行完成。當設定項 balance
配置為 false
時,Horizon 會使用 Laravel 預設執行行為,它將依照設定中列出的順序處理佇列任務。
任務修整
horizon
設定檔允許你設定應保留最近和失敗任務的時間(以分鐘為單位)。預設情況下,最近的任務保留一小時,而失敗的任務保留一周:
'trim' => [ 'recent' => 60, 'failed' => 10080, ],
#儀表板權限驗證
Horizon 儀表板路由是/horizon
。預設情況下,你只能在 local
環境下存取儀錶板。在你的 app/Providers/HorizonServiceProvider.php
檔案中,有一個 gate
方法。這裡授權控制 非本地 環境中對 Horizon 的存取。你可以根據需要隨意修改此門面,以限制對Horizon 安裝的存取:
/** * 注册 Horizon gate 方法 * * gate 决定了谁可以在非本地环境中访问 Horizon。 * * @return void */ protected function gate(){ Gate::define('viewHorizon', function ($user) { return in_array($user->email, [ 'taylor@laravel.com', ]); }); }
#運行Horizon
當在config /horizon.php
檔案中配置好了你的佇列執行進程後,你就可以使用horizon
Artisan 指令啟動Horizon。只需要一條指令語句即可啟動所有設定好的佇列程序:
php artisan horizon
你也可以使用horizon:pause
和horizon:continue
Artisan 指令來暫停或繼續執行佇列任務:
php artisan horizon:pausephp artisan horizon:continue
你可以使用horizon:terminate
Artisan 指令優雅的終止Horizon 主程序。 Horizon 會把正在執行的任務處理完畢後退出:
php artisan horizon:terminate#
部署 Horizon
如果你將 Horizon 部署到線上伺服器時,則需要設定一個進程監視器來偵測 php artisan horizon
指令,在它意外退出時會自動重新啟動。上線新程式碼時則需要該進程監視器終止 Horizon 進程並以修改後的程式碼重新啟動 Horizon。
Supervisor 設定
如果你使用Supervisor 進程監控器管理你的horizon
進程,那麼以下設定檔則可滿足需求:
[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} 如果你不喜歡自己維護伺服器,可以考慮使用Laravel Forge,Forge 提供了運行一個帶有Horizon 的現代、強大的Laravel 應用所需要的PHP7 及其他所有環境。
標籤
Horizon 允許你對任務分配「標籤」,包括郵件,事件廣播,通知和隊列的事件監聽器。事實上,Horizon 會智慧並且自動根據任務攜帶Eloquent 模型給大多數任務標記標籤,如下任務範例:
<?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 实例 * * @var \App\Video */ public $video; /** * 创建工作实例 * * @param \App\Video $video * @return void */ public function __construct(Video $video) { $this->video = $video; } /** * 执行任务 * * @return void */ public function handle() { // } }
如果該佇列任務是一個攜帶id
為1
的App\Video
實例,那麼它將自動被標記上App\Video:1
標籤。因為Horizon 會檢查任務屬性是否具有Eloquent 模型,如果發現Eloquent 模型,Horizon 將會智慧的用該模型的類別名稱和主鍵為任務標記上標籤:
$video = App\Video::find(1); App\Jobs\RenderVideo::dispatch($video);
自訂標籤
#如果你想手動的為佇列執行的物件定義標籤,你可以給這個類別定義一個tags
方法:
class RenderVideo implements ShouldQueue{ /** * 获取分配给这个任务的标签 * * @return array */ public function tags() { return ['render', 'video:'.$this->video->id]; } }##通知
如果需要在佇列等待時間過長時發起通知,可以在應用的Note: 在使用通知之前,你應該要加上guzzlehttp/guzzle
Composer 套件到你的專案。在使用 Horizon 設定發送簡訊通知時,你也應該閱讀
Nexmo 通知驅動的依賴條件章節。
AppServiceProvider 中呼叫
Horizon::routeMailNotificationsTo#,
Horizon: :routeSlackNotificationsTo, 和
Horizon::routeSmsNotificationsTo 方法:
Horizon::routeMailNotificationsTo('example@example.com'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel'); Horizon::routeSmsNotificationsTo('15556667777');配置等待時間過長的閾值你可以在
config/horizon.php 在設定檔中設定等待時間過長的特定秒數。
waits 設定項可以針對每一個連結/ 隊列配置閾值:
'waits' => [ 'redis:default' => 60, ],Metrics
##Horizon 包含一個Metrics 儀表盤,它可以提供任務和隊列等待時間和吞吐量信息,為了填充此儀錶盤,你需要配置應用的scheduler 每五分鐘運行一次Horizon 的
snapshot Artisan 命令:/**
* 定义应用程序的任务调度
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $schedule){
$schedule->command('horizon:snapshot')->everyFiveMinutes();
}