はじめに

Laravel Horizon に入る前に、Laravel の基本的な キューサービス に慣れておくべきです。Horizon は Laravel のキューに追加機能を加えますが、Laravel が提供する基本的なキュー機能に慣れていないと混乱するかもしれません。

Laravel Horizon は、美しいダッシュボードとコード駆動の設定を提供し、Laravel によって動かされる Redis キュー を管理します。Horizon を使用すると、ジョブのスループット、実行時間、ジョブの失敗など、キューシステムの重要なメトリクスを簡単に監視できます。

Horizon を使用する際は、すべてのキュー作業者の設定が単一のシンプルな設定ファイルに保存されます。アプリケーションの作業者設定をバージョン管理されたファイルに定義することで、アプリケーションをデプロイする際にキュー作業者を簡単にスケールまたは変更できます。
Horizon - img1

インストール

Laravel Horizon を使用するには、キューを動かすために Redis を使用する必要があります。したがって、アプリケーションの config/queue.php 設定ファイルでキュー接続が redis に設定されていることを確認してください。

Composer パッケージマネージャーを使用して、プロジェクトに Horizon をインストールできます:

  1. composer require laravel/horizon

Horizon をインストールした後、horizon:install Artisan コマンドを使用してそのアセットを公開します:

  1. php artisan horizon:install

設定

Horizon のアセットを公開した後、その主な設定ファイルは config/horizon.php にあります。この設定ファイルでは、アプリケーションのキュー作業者オプションを設定できます。各設定オプションにはその目的の説明が含まれているので、このファイルを十分に探検してください。

Horizon は内部で horizon という名前の Redis 接続を使用します。この Redis 接続名は予約されており、database.php 設定ファイル内の他の Redis 接続に割り当てたり、use オプションの値として使用したりしないでください。

環境

インストール後、慣れておくべき主な Horizon 設定オプションは environments 設定オプションです。この設定オプションは、アプリケーションが実行される環境の配列であり、各環境の作業者プロセスオプションを定義します。デフォルトでは、このエントリには productionlocal 環境が含まれています。ただし、必要に応じてさらに環境を追加することができます:

  1. 'environments' => [
  2. 'production' => [
  3. 'supervisor-1' => [
  4. 'maxProcesses' => 10,
  5. 'balanceMaxShift' => 1,
  6. 'balanceCooldown' => 3,
  7. ],
  8. ],
  9. 'local' => [
  10. 'supervisor-1' => [
  11. 'maxProcesses' => 3,
  12. ],
  13. ],
  14. ],

また、他の一致する環境が見つからない場合に使用されるワイルドカード環境 (*) を定義することもできます:

  1. 'environments' => [
  2. // ...
  3. '*' => [
  4. 'supervisor-1' => [
  5. 'maxProcesses' => 3,
  6. ],
  7. ],
  8. ],

Horizon を起動すると、アプリケーションが実行されている環境の作業者プロセス設定オプションが使用されます。通常、環境は APP_ENV 環境変数 の値によって決まります。たとえば、デフォルトの local Horizon 環境は、3 つの作業者プロセスを起動し、各キューに割り当てられた作業者プロセスの数を自動的にバランスさせるように設定されています。デフォルトの production 環境は、最大 10 の作業者プロセスを起動し、各キューに割り当てられた作業者プロセスの数を自動的にバランスさせるように設定されています。

environments の部分が、Horizon を実行する予定の各 環境 のエントリを含んでいることを確認してください。

スーパーバイザー

Horizon のデフォルト設定ファイルに見られるように、各環境には 1 つ以上の「スーパーバイザー」を含めることができます。デフォルトでは、設定ファイルはこのスーパーバイザーを supervisor-1 と定義していますが、スーパーバイザーに好きな名前を付けることができます。各スーパーバイザーは、作業者プロセスのグループを「監視」し、キュー間で作業者プロセスのバランスを取る役割を担っています。

特定の環境に追加のスーパーバイザーを追加することで、その環境で実行される新しい作業者プロセスのグループを定義することができます。特定のキューに対して異なるバランス戦略や作業者プロセスの数を定義したい場合は、これを選択することができます。

メンテナンスモード

アプリケーションが メンテナンスモード の場合、スーパーバイザーの force オプションが Horizon 設定ファイル内で true と定義されていない限り、キューに入れられたジョブは Horizon によって処理されません:

  1. 'environments' => [
  2. 'production' => [
  3. 'supervisor-1' => [
  4. // ...
  5. 'force' => true,
  6. ],
  7. ],
  8. ],

デフォルト値

Horizon のデフォルト設定ファイル内には、defaults 設定オプションがあります。この設定オプションは、アプリケーションの スーパーバイザー のデフォルト値を指定します。スーパーバイザーのデフォルト設定値は、各環境のスーパーバイザーの設定にマージされ、スーパーバイザーを定義する際の不必要な繰り返しを避けることができます。

バランス戦略

Laravel のデフォルトキューシステムとは異なり、Horizon では 3 つの作業者バランス戦略から選択できます: simpleautofalsesimple 戦略は、受信したジョブを作業者プロセス間で均等に分配します:

  1. 'balance' => 'simple',

auto 戦略は、設定ファイルのデフォルトであり、キューの現在の負荷に基づいてキューごとの作業者プロセスの数を調整します。たとえば、notifications キューに 1,000 件の保留中のジョブがあり、render キューが空である場合、Horizon は notifications キューにより多くの作業者を割り当て、キューが空になるまで続けます。

auto 戦略を使用する場合、minProcesses および maxProcesses 設定オプションを定義して、キューごとの最小プロセス数と、Horizon がスケールアップおよびスケールダウンする際の最大作業者プロセス数を制御できます:

  1. 'environments' => [
  2. 'production' => [
  3. 'supervisor-1' => [
  4. 'connection' => 'redis',
  5. 'queue' => ['default'],
  6. 'balance' => 'auto',
  7. 'autoScalingStrategy' => 'time',
  8. 'minProcesses' => 1,
  9. 'maxProcesses' => 10,
  10. 'balanceMaxShift' => 1,
  11. 'balanceCooldown' => 3,
  12. 'tries' => 3,
  13. ],
  14. ],
  15. ],

autoScalingStrategy 設定値は、Horizon がキューをクリアするのにかかる合計時間 (time 戦略) またはキュー上のジョブの合計数 (size 戦略) に基づいて、より多くの作業者プロセスをキューに割り当てるかどうかを決定します。

balanceMaxShift および balanceCooldown 設定値は、Horizon が作業者の需要に応じてどれだけ迅速にスケールするかを決定します。上記の例では、最大で 3 秒ごとに 1 つの新しいプロセスが作成または破棄されます。アプリケーションのニーズに応じて、これらの値を調整することができます。

balance オプションが false に設定されている場合、デフォルトの Laravel の動作が使用され、キューは設定にリストされている順序で処理されます。

ダッシュボードの認可

Horizon ダッシュボードには /horizon ルートを介してアクセスできます。デフォルトでは、local 環境でのみこのダッシュボードにアクセスできます。ただし、app/Providers/HorizonServiceProvider.php ファイル内には 認可ゲート の定義があります。この認可ゲートは、非ローカル 環境での Horizon へのアクセスを制御します。必要に応じてこのゲートを変更して、Horizon インストールへのアクセスを制限できます:

  1. /**
  2. * Register the Horizon gate.
  3. *
  4. * This gate determines who can access Horizon in non-local environments.
  5. */
  6. protected function gate(): void
  7. {
  8. Gate::define('viewHorizon', function (User $user) {
  9. return in_array($user->email, [
  10. '',
  11. ]);
  12. });
  13. }

代替認証戦略

Laravel は自動的に認証されたユーザーをゲートクロージャに注入します。アプリケーションが IP 制限などの別の方法で Horizon セキュリティを提供している場合、Horizon ユーザーは「ログイン」する必要がないかもしれません。したがって、Laravel に認証を必要としないように強制するために、上記の function (User $user) クロージャのシグネチャを function (User $user = null) に変更する必要があります。

サイレントジョブ

時には、アプリケーションやサードパーティパッケージによって送信された特定のジョブを表示したくない場合があります。これらのジョブが「完了したジョブ」リストにスペースを取る代わりに、サイレントにすることができます。始めるには、アプリケーションの horizon 設定ファイルの silenced 設定オプションにジョブのクラス名を追加します:

  1. 'silenced' => [
  2. App\Jobs\ProcessPodcast::class,
  3. ],

また、サイレントにしたいジョブは Laravel\Horizon\Contracts\Silenced インターフェースを実装できます。このインターフェースを実装したジョブは、silenced 設定配列に存在しなくても自動的にサイレントになります:

  1. use Laravel\Horizon\Contracts\Silenced;
  2. class ProcessPodcast implements ShouldQueue, Silenced
  3. {
  4. use Queueable;
  5. // ...
  6. }

Horizon のアップグレード

Horizon の新しいメジャーバージョンにアップグレードする際は、アップグレードガイド を注意深く確認することが重要です。

Horizon の実行

アプリケーションの config/horizon.php 設定ファイルでスーパーバイザーと作業者を設定したら、horizon Artisan コマンドを使用して Horizon を起動できます。この単一のコマンドは、現在の環境のすべての設定された作業者プロセスを起動します:

  1. php artisan horizon

Horizon プロセスを一時停止し、horizon:pause および horizon:continue Artisan コマンドを使用してジョブの処理を続行するよう指示できます:

  1. php artisan horizon:pause
  2. php artisan horizon:continue

特定の Horizon スーパーバイザーhorizon:pause-supervisor および horizon:continue-supervisor Artisan コマンドを使用して一時停止および続行することもできます:

  1. php artisan horizon:pause-supervisor supervisor-1
  2. php artisan horizon:continue-supervisor supervisor-1

Horizon プロセスの現在の状態を horizon:status Artisan コマンドを使用して確認できます:

  1. php artisan horizon:status

Horizon プロセスを優雅に終了するには、horizon:terminate Artisan コマンドを使用します。現在処理中のジョブは完了し、その後 Horizon の実行が停止します:

  1. php artisan horizon:terminate

Horizon のデプロイ

Horizon をアプリケーションの実際のサーバーにデプロイする準備ができたら、プロセスモニターを設定して php artisan horizon コマンドを監視し、予期せず終了した場合に再起動するようにします。心配しないでください。プロセスモニターのインストール方法については、以下で説明します。

アプリケーションのデプロイプロセス中に、Horizon プロセスを終了するよう指示し、プロセスモニターによって再起動され、コード変更を受け取るようにします:

  1. php artisan horizon:terminate

スーパーバイザーのインストール

スーパーバイザーは Linux オペレーティングシステム用のプロセスモニターであり、実行が停止した場合に自動的に horizon プロセスを再起動します。Ubuntu にスーパーバイザーをインストールするには、次のコマンドを使用できます。Ubuntu を使用していない場合は、オペレーティングシステムのパッケージマネージャーを使用してスーパーバイザーをインストールできる可能性があります:

  1. sudo apt-get install supervisor

スーパーバイザーを自分で設定するのが大変に感じる場合は、Laravel Forge を使用することを検討してください。これにより、Laravel プロジェクト用にスーパーバイザーが自動的にインストールおよび設定されます。

スーパーバイザー設定

スーパーバイザーの設定ファイルは通常、サーバーの /etc/supervisor/conf.d ディレクトリ内に保存されます。このディレクトリ内で、スーパーバイザーがプロセスをどのように監視するかを指示する任意の数の設定ファイルを作成できます。たとえば、horizon.conf ファイルを作成して horizon プロセスを開始および監視しましょう:

  1. [program:horizon]
  2. process_name=%(program_name)s
  3. command=php /home/forge/example.com/artisan horizon
  4. autostart=true
  5. autorestart=true
  6. user=forge
  7. redirect_stderr=true
  8. stdout_logfile=/home/forge/example.com/horizon.log
  9. stopwaitsecs=3600

スーパーバイザーの設定を定義する際は、stopwaitsecs の値が最も長く実行されるジョブによって消費される秒数より大きいことを確認してください。そうしないと、スーパーバイザーがジョブを処理が完了する前に終了させる可能性があります。

上記の例は Ubuntu ベースのサーバーに有効ですが、スーパーバイザーの設定ファイルに期待される場所やファイル拡張子は、他のサーバーオペレーティングシステムによって異なる場合があります。詳細については、サーバーのドキュメントを参照してください。

スーパーバイザーの起動

設定ファイルが作成されたら、次のコマンドを使用してスーパーバイザーの設定を更新し、監視されるプロセスを起動できます:

  1. sudo supervisorctl reread
  2. sudo supervisorctl update
  3. sudo supervisorctl start horizon

スーパーバイザーの実行に関する詳細は、スーパーバイザーのドキュメント を参照してください。

タグ

Horizon では、メール、ブロードキャストイベント、通知、キューイベントリスナーなどのジョブに「タグ」を割り当てることができます。実際、Horizon は、ジョブに添付された Eloquent モデルに基づいてほとんどのジョブをインテリジェントに自動的にタグ付けします。たとえば、次のジョブを見てみましょう:

  1. <?php
  2. namespace App\Jobs;
  3. use App\Models\Video;
  4. use Illuminate\Contracts\Queue\ShouldQueue;
  5. use Illuminate\Foundation\Queue\Queueable;
  6. class RenderVideo implements ShouldQueue
  7. {
  8. use Queueable;
  9. /**
  10. * Create a new job instance.
  11. */
  12. public function __construct(
  13. public Video $video,
  14. ) {}
  15. /**
  16. * Execute the job.
  17. */
  18. public function handle(): void
  19. {
  20. // ...
  21. }
  22. }

このジョブが App\Models\Video インスタンスと共にキューに入れられ、id 属性が 1 の場合、自動的に App\Models\Video:1 タグが付けられます。これは、Horizon がジョブのプロパティを検索して Eloquent モデルを探すためです。Eloquent モデルが見つかると、Horizon はインテリジェントにモデルのクラス名と主キーを使用してジョブにタグを付けます:

  1. use App\Jobs\RenderVideo;
  2. use App\Models\Video;
  3. $video = Video::find(1);
  4. RenderVideo::dispatch($video);

ジョブの手動タグ付け

キュー可能なオブジェクトのタグを手動で定義したい場合は、クラスに tags メソッドを定義できます:

  1. class RenderVideo implements ShouldQueue
  2. {
  3. /**
  4. * Get the tags that should be assigned to the job.
  5. *
  6. * @return array<int, string>
  7. */
  8. public function tags(): array
  9. {
  10. return ['render', 'video:'.$this->video->id];
  11. }
  12. }

イベントリスナーの手動タグ付け

キューに入れられたイベントリスナーのタグを取得する際、Horizon は自動的にイベントインスタンスを tags メソッドに渡し、タグにイベントデータを追加できるようにします:

  1. class SendRenderNotifications implements ShouldQueue
  2. {
  3. /**
  4. * Get the tags that should be assigned to the listener.
  5. *
  6. * @return array<int, string>
  7. */
  8. public function tags(VideoRendered $event): array
  9. {
  10. return ['video:'.$event->video->id];
  11. }
  12. }

通知

Horizon を Slack や SMS 通知を送信するように設定する際は、関連する通知チャネルの 前提条件 を確認してください。

キューの待機時間が長い場合に通知を受け取りたい場合は、Horizon::routeMailNotificationsToHorizon::routeSlackNotificationsTo、および Horizon::routeSmsNotificationsTo メソッドを使用できます。これらのメソッドは、アプリケーションの App\Providers\HorizonServiceProvider メソッドから呼び出すことができます:

  1. /**
  2. * Bootstrap any application services.
  3. */
  4. public function boot(): void
  5. {
  6. parent::boot();
  7. Horizon::routeSmsNotificationsTo('15556667777');
  8. Horizon::routeMailNotificationsTo('');
  9. Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
  10. }

通知の待機時間しきい値の設定

アプリケーションの config/horizon.php 設定ファイル内で、何秒が「長い待機」と見なされるかを設定できます。このファイル内の waits 設定オプションを使用して、各接続/キューの組み合わせに対する長い待機しきい値を制御できます。未定義の接続/キューの組み合わせは、デフォルトで 60 秒の長い待機しきい値になります:

  1. 'waits' => [
  2. 'redis:critical' => 30,
  3. 'redis:default' => 60,
  4. 'redis:batch' => 120,
  5. ],

メトリクス

Horizon には、ジョブとキューの待機時間およびスループットに関する情報を提供するメトリクスダッシュボードが含まれています。このダッシュボードをポピュレートするには、アプリケーションの routes/console.php ファイル内で Horizon の snapshot Artisan コマンドを 5 分ごとに実行するように設定する必要があります:

  1. use Illuminate\Support\Facades\Schedule;
  2. Schedule::command('horizon:snapshot')->everyFiveMinutes();

失敗したジョブの削除

失敗したジョブを削除したい場合は、horizon:forget コマンドを使用できます。horizon:forget コマンドは、失敗したジョブの ID または UUID を唯一の引数として受け取ります:

  1. php artisan horizon:forget 5

すべての失敗したジョブを削除したい場合は、horizon:forget コマンドに --all オプションを提供できます:

  1. php artisan horizon:forget --all

キューからのジョブのクリア

アプリケーションのデフォルトキューからすべてのジョブを削除したい場合は、horizon:clear Artisan コマンドを使用して削除できます:

  1. php artisan horizon:clear

特定のキューからジョブを削除するには、queue オプションを提供できます:

  1. php artisan horizon:clear --queue=emails