Laravel Horizon
はじめに
Laravel Horizonを深く掘り下げる前に、Laravelの基本的なキューサービスに精通しておく必要があります。HorizonはLaravelのキューに追加機能を提供しますが、Laravelが提供する基本的なキュー機能に慣れていない場合は、混乱を招く可能性があります。
Laravel Horizon は、Laravel対応のRedisキューのために、美しいダッシュボードとコード駆動型の設定を提供します。Horizonを使用すると、ジョブのスループット、実行時間、ジョブの失敗など、キューシステムの主要なメトリクスを簡単に監視できます。
Horizonを使用する場合、キューワーカーの設定はすべて、シンプルで単一の設定ファイルに保存されます。アプリケーションのワーカー設定をバージョン管理されたファイルで定義することで、アプリケーションのデプロイ時にキューワーカーを簡単にスケールまたは変更できます。

インストール
Laravel Horizonを使用するには、Redis をキューの基盤として使用する必要があります。そのため、アプリケーションのconfig/queue.php
設定ファイルで、キュー接続がredis
に設定されていることを確認する必要があります。
Composerパッケージマネージャーを使用して、プロジェクトにHorizonをインストールできます。
composer require laravel/horizon
Horizonをインストールした後、horizon:install
Artisanコマンドを使用してアセットを公開します。
php artisan horizon:install
設定
Horizonのアセットを公開した後、その主要な設定ファイルはconfig/horizon.php
にあります。この設定ファイルでは、アプリケーションのキューワーカーオプションを設定できます。各設定オプションには目的の説明が含まれているため、このファイルを徹底的に調べてください。
Horizonは内部的にhorizon
という名前のRedis接続を使用します。このRedis接続名は予約済みであり、database.php
設定ファイルで別のRedis接続に割り当てたり、horizon.php
設定ファイルのuse
オプションの値として使用したりしないでください。
環境
インストール後、最初に理解しておくべきHorizonの主要な設定オプションは、environments
設定オプションです。この設定オプションは、アプリケーションが実行されている環境の配列であり、各環境のワーカープロセスのオプションを定義します。デフォルトでは、このエントリにはproduction
とlocal
環境が含まれています。ただし、必要に応じてさらに環境を追加できます。
'environments' => [ 'production' => [ 'supervisor-1' => [ 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, ], ], 'local' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
ワイルドカード環境(*
)も定義できます。これは、他の一致する環境が見つからない場合に使用されます。
'environments' => [ // ... '*' => [ 'supervisor-1' => [ 'maxProcesses' => 3, ], ],],
Horizonを起動すると、アプリケーションが実行されている環境のワーカープロセスの設定オプションが使用されます。通常、環境はAPP_ENV
環境変数の値によって決定されます。たとえば、デフォルトのlocal
Horizon環境は、3つのワーカープロセスを開始し、各キューに割り当てられたワーカープロセスの数を自動的にバランスするように設定されています。デフォルトのproduction
環境は、最大10個のワーカープロセスを開始し、各キューに割り当てられたワーカープロセスの数を自動的にバランスするように設定されています。
horizon
設定ファイルのenvironments
セクションに、Horizonを実行する予定の各環境のエントリが含まれていることを確認する必要があります。
スーパーバイザー
Horizonのデフォルトの設定ファイルに見られるように、各環境には1つ以上の「スーパーバイザー」を含めることができます。デフォルトでは、設定ファイルはこのスーパーバイザーをsupervisor-1
として定義していますが、スーパーバイザーの名前は自由に付けることができます。各スーパーバイザーは本質的に、ワーカープロセスのグループを「監視」する役割を担い、キュー間でワーカープロセスをバランスさせる役割を果たします。
特定の環境にスーパーバイザーを追加して、その環境で実行する必要がある新しいワーカープロセスのグループを定義することもできます。これは、アプリケーションで使用される特定のキューに対して、異なるバランス戦略またはワーカープロセスの数を定義したい場合に行うことができます。
メンテナンスモード
アプリケーションがメンテナンスモードになっている間は、Horizon設定ファイル内でスーパーバイザーのforce
オプションがtrue
として定義されていない限り、キュージョブはHorizonによって処理されません。
'environments' => [ 'production' => [ 'supervisor-1' => [ // ... 'force' => true, ], ],],
デフォルト値
Horizonのデフォルトの設定ファイルでは、defaults
設定オプションに注目してください。この設定オプションは、アプリケーションのスーパーバイザーのデフォルト値を指定します。スーパーバイザーのデフォルトの設定値は、各環境のスーパーバイザーの設定にマージされるため、スーパーバイザーを定義する際に不要な繰り返しを避けることができます。
バランス戦略
Laravelのデフォルトのキューシステムとは異なり、Horizonでは、simple
、auto
、false
の3つのワーカーバランス戦略から選択できます。simple
戦略は、着信ジョブをワーカープロセス間で均等に分割します。
'balance' => 'simple',
設定ファイルのデフォルトであるauto
戦略は、キューの現在のワークロードに基づいて、キューあたりのワーカープロセスの数を調整します。たとえば、notifications
キューに1,000件の保留中のジョブがあり、render
キューが空の場合、Horizonはnotifications
キューが空になるまで、notifications
キューにより多くのワーカーを割り当てます。
auto
戦略を使用する場合、minProcesses
とmaxProcesses
設定オプションを定義して、キューあたりの最小プロセス数と、Horizonがスケールアップおよびスケールダウンする最大ワーカープロセス数を制御できます。
'environments' => [ 'production' => [ 'supervisor-1' => [ 'connection' => 'redis', 'queue' => ['default'], 'balance' => 'auto', 'autoScalingStrategy' => 'time', 'minProcesses' => 1, 'maxProcesses' => 10, 'balanceMaxShift' => 1, 'balanceCooldown' => 3, 'tries' => 3, ], ],],
autoScalingStrategy
設定値は、Horizon がキューのクリアに必要な総時間 (time
戦略) 、またはキュー上のジョブの総数 (size
戦略) に基づいて、キューにワーカープロセスを追加するかどうかを決定します。
balanceMaxShift
と balanceCooldown
設定値は、Horizon がワーカーの需要を満たすためにスケールする速度を決定します。上記の例では、3 秒ごとに最大で 1 つの新しいプロセスが作成または破棄されます。アプリケーションのニーズに応じて、これらの値を必要に応じて調整できます。
balance
オプションが false
に設定されている場合、デフォルトの Laravel の動作が使用されます。この動作では、キューは設定ファイルにリストされている順番で処理されます。
ダッシュボード認証
Horizon ダッシュボードは、/horizon
ルートからアクセスできます。デフォルトでは、local
環境でのみこのダッシュボードにアクセスできます。ただし、app/Providers/HorizonServiceProvider.php
ファイルには、承認ゲート の定義があります。この承認ゲートは、**ローカル環境以外**の Horizon へのアクセスを制御します。Horizon インストールへのアクセスを制限するために、必要に応じてこのゲートを変更できます。
/** * Register the Horizon gate. * * This gate determines who can access Horizon in non-local environments. */protected function gate(): void{ Gate::define('viewHorizon', function (User $user) { return in_array($user->email, [ ]); });}
代替認証戦略
Laravel は認証済みユーザーをゲートクロージャに自動的に注入することに注意してください。アプリケーションが IP 制限などの別の方法で Horizon のセキュリティを提供している場合、Horizon ユーザーは「ログイン」する必要がない場合があります。したがって、Laravel に認証を要求させないようにするには、上記の function (User $user)
クロージャのシグネチャを function (User $user = null)
に変更する必要があります。
サイレントジョブ
アプリケーションまたはサードパーティパッケージによってディスパッチされた特定のジョブの表示に興味がない場合があります。「完了したジョブ」リストにこれらのジョブが表示されないようにするには、サイレント化できます。開始するには、アプリケーションの horizon
設定ファイルの silenced
設定オプションにジョブのクラス名を追加します。
'silenced' => [ App\Jobs\ProcessPodcast::class,],
あるいは、サイレント化したいジョブは、Laravel\Horizon\Contracts\Silenced
インターフェースを実装できます。ジョブがこのインターフェースを実装している場合、silenced
設定配列に存在しなくても、自動的にサイレント化されます。
use Laravel\Horizon\Contracts\Silenced; class ProcessPodcast implements ShouldQueue, Silenced{ use Queueable; // ...}
Horizonのアップグレード
Horizon の新しいメジャーバージョンにアップグレードする際には、アップグレードガイド を注意深く確認することが重要です。
Horizonの実行
アプリケーションの config/horizon.php
設定ファイルでスーパーバイザーとワーカーを設定したら、horizon
Artisan コマンドを使用して Horizon を開始できます。この単一のコマンドは、現在の環境に対して設定されたすべてのワーカープロセスを開始します。
php artisan horizon
horizon:pause
と horizon:continue
Artisan コマンドを使用して、Horizon プロセスを一時停止し、ジョブの処理を再開するように指示できます。
php artisan horizon:pause php artisan horizon:continue
horizon:pause-supervisor
と horizon:continue-supervisor
Artisan コマンドを使用して、特定の Horizon スーパーバイザー を一時停止および再開することもできます。
php artisan horizon:pause-supervisor supervisor-1 php artisan horizon:continue-supervisor supervisor-1
horizon:status
Artisan コマンドを使用して、Horizon プロセスの現在の状態を確認できます。
php artisan horizon:status
horizon:supervisor-status
Artisan コマンドを使用して、特定の Horizon スーパーバイザー の現在の状態を確認できます。
php artisan horizon:supervisor-status supervisor-1
horizon:terminate
Artisan コマンドを使用して、Horizon プロセスを正常に終了できます。現在処理中のジョブは完了し、その後 Horizon は実行を停止します。
php artisan horizon:terminate
Horizonのデプロイ
Horizon をアプリケーションの実際のサーバーにデプロイする準備ができたら、php artisan horizon
コマンドを監視し、予期せず終了した場合に再起動するプロセスモニターを設定する必要があります。心配しないでください。以下でプロセスモニターのインストール方法について説明します。
アプリケーションのデプロイプロセス中に、Horizon プロセスを終了するように指示する必要があります。これにより、プロセスモニターによって再起動され、コードの変更が反映されます。
php artisan horizon:terminate
Supervisor のインストール
Supervisor は Linux オペレーティングシステムのプロセスモニターであり、horizon
プロセスが実行を停止した場合に自動的に再起動します。Ubuntu に Supervisor をインストールするには、次のコマンドを使用できます。Ubuntu を使用していない場合は、オペレーティングシステムのパッケージマネージャーを使用して Supervisor をインストールできる可能性があります。
sudo apt-get install supervisor
Supervisor の自身による設定が困難な場合は、Laravel Forge を使用することを検討してください。Laravel Forge は、Laravel プロジェクトの Supervisor を自動的にインストールして設定します。
Supervisor の設定
Supervisor の設定ファイルは、通常、サーバーの /etc/supervisor/conf.d
ディレクトリに保存されます。このディレクトリでは、プロセスを監視する方法を Supervisor に指示する設定ファイルをいくつでも作成できます。たとえば、horizon
プロセスを開始して監視する horizon.conf
ファイルを作成してみましょう。
[program:horizon]process_name=%(program_name)scommand=php /home/forge/example.com/artisan horizonautostart=trueautorestart=trueuser=forgeredirect_stderr=truestdout_logfile=/home/forge/example.com/horizon.logstopwaitsecs=3600
Supervisor の設定を定義する際には、stopwaitsecs
の値が、最も長く実行されるジョブによって消費される秒数よりも大きくなるようにする必要があります。そうでない場合、Supervisor はジョブが処理を完了する前にジョブを強制終了する可能性があります。
上記の例は Ubuntu ベースのサーバーで有効ですが、Supervisor 設定ファイルの場所とファイル拡張子は、他のサーバーオペレーティングシステムによって異なる場合があります。詳細については、サーバーのドキュメントを参照してください。
Supervisor の開始
設定ファイルを作成したら、次のコマンドを使用して Supervisor の設定を更新し、監視対象のプロセスを開始できます。
sudo supervisorctl reread sudo supervisorctl update sudo supervisorctl start horizon
Supervisor の実行の詳細については、Supervisor のドキュメント を参照してください。
タグ
Horizon を使用すると、メール、ブロードキャストイベント、通知、キューされたイベントリスナーなど、ジョブに「タグ」を付けることができます。実際、Horizon は、ジョブに添付されている Eloquent モデルに応じて、ほとんどのジョブをインテリジェントに自動的にタグ付けします。たとえば、次のジョブを見てみましょう。
<?php namespace App\Jobs; use App\Models\Video;use Illuminate\Contracts\Queue\ShouldQueue;use Illuminate\Foundation\Queue\Queueable; class RenderVideo implements ShouldQueue{ use Queueable; /** * Create a new job instance. */ public function __construct( public Video $video, ) {} /** * Execute the job. */ public function handle(): void { // ... }}
このジョブが id
属性が 1
の App\Models\Video
インスタンスとともにキューに入れられる場合、自動的に App\Models\Video:1
タグが付きます。これは、Horizon がジョブのプロパティで Eloquent モデルを検索するためです。Eloquent モデルが見つかった場合、Horizon はモデルのクラス名と主キーを使用してジョブをインテリジェントにタグ付けします。
use App\Jobs\RenderVideo;use App\Models\Video; $video = Video::find(1); RenderVideo::dispatch($video);
ジョブの手動タグ付け
キュー可能なオブジェクトのタグを手動で定義する場合は、クラスに tags
メソッドを定義できます。
class RenderVideo implements ShouldQueue{ /** * Get the tags that should be assigned to the job. * * @return array<int, string> */ public function tags(): array { return ['render', 'video:'.$this->video->id]; }}
イベントリスナーの手動タグ付け
キューされたイベントリスナーのタグを取得する場合、Horizon はイベントインスタンスを tags
メソッドに自動的に渡すため、イベントデータをタグに追加できます。
class SendRenderNotifications implements ShouldQueue{ /** * Get the tags that should be assigned to the listener. * * @return array<int, string> */ public function tags(VideoRendered $event): array { return ['video:'.$event->video->id]; }}
通知
Slack または SMS 通知を送信するように Horizon を設定する際には、関連する通知チャネルの前提条件 を確認する必要があります。
キューのいずれかの待機時間が長い場合に通知を受け取る場合は、Horizon::routeMailNotificationsTo
、Horizon::routeSlackNotificationsTo
、Horizon::routeSmsNotificationsTo
メソッドを使用できます。これらのメソッドは、アプリケーションの App\Providers\HorizonServiceProvider
の boot
メソッドから呼び出すことができます。
/** * Bootstrap any application services. */public function boot(): void{ parent::boot(); Horizon::routeSmsNotificationsTo('15556667777'); Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');}
通知待機時間しきい値の設定
アプリケーションの config/horizon.php
設定ファイル内で、「長い待機時間」と見なされる秒数を設定できます。このファイル内の waits
設定オプションを使用すると、接続/キューの組み合わせごとに長い待機時間しきい値を制御できます。未定義の接続/キューの組み合わせは、デフォルトで 60 秒の長い待機時間しきい値になります。
'waits' => [ 'redis:critical' => 30, 'redis:default' => 60, 'redis:batch' => 120,],
メトリクス
Horizon には、ジョブとキューの待機時間とスループットに関する情報を提供するメトリックスダッシュボードが含まれています。このダッシュボードにデータを入力するには、アプリケーションの routes/console.php
ファイルで Horizon の snapshot
Artisan コマンドが 5 分ごとに実行されるように設定する必要があります。
use Illuminate\Support\Facades\Schedule; Schedule::command('horizon:snapshot')->everyFiveMinutes();
失敗したジョブの削除
失敗したジョブを削除する場合は、horizon:forget
コマンドを使用できます。horizon:forget
コマンドは、失敗したジョブの ID または UUID を唯一の引数として受け入れます。
php artisan horizon:forget 5
すべての失敗したジョブを削除する場合は、horizon:forget
コマンドに --all
オプションを指定できます。
php artisan horizon:forget --all
キューからのジョブのクリア
アプリケーションのデフォルトキューからすべてのジョブを削除する場合は、horizon:clear
Artisan コマンドを使用できます。
php artisan horizon:clear
特定のキューからジョブを削除するには、queue
オプションを指定できます。
php artisan horizon:clear --queue=emails