はじめに
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 接続に割り当てたり、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 の作業者プロセスを起動し、各キューに割り当てられた作業者プロセスの数を自動的にバランスさせるように設定されています。
environments
の部分が、Horizon を実行する予定の各 環境 のエントリを含んでいることを確認してください。
スーパーバイザー
Horizon のデフォルト設定ファイルに見られるように、各環境には 1 つ以上の「スーパーバイザー」を含めることができます。デフォルトでは、設定ファイルはこのスーパーバイザーを supervisor-1
と定義していますが、スーパーバイザーに好きな名前を付けることができます。各スーパーバイザーは、作業者プロセスのグループを「監視」し、キュー間で作業者プロセスのバランスを取る役割を担っています。
特定の環境に追加のスーパーバイザーを追加することで、その環境で実行される新しい作業者プロセスのグループを定義することができます。特定のキューに対して異なるバランス戦略や作業者プロセスの数を定義したい場合は、これを選択することができます。
メンテナンスモード
アプリケーションが メンテナンスモード の場合、スーパーバイザーの force
オプションが Horizon 設定ファイル内で true
と定義されていない限り、キューに入れられたジョブは Horizon によって処理されません:
'environments' => [
'production' => [
'supervisor-1' => [
// ...
'force' => true,
],
],
],
デフォルト値
Horizon のデフォルト設定ファイル内には、defaults
設定オプションがあります。この設定オプションは、アプリケーションの スーパーバイザー のデフォルト値を指定します。スーパーバイザーのデフォルト設定値は、各環境のスーパーバイザーの設定にマージされ、スーパーバイザーを定義する際の不必要な繰り返しを避けることができます。
バランス戦略
Laravel のデフォルトキューシステムとは異なり、Horizon では 3 つの作業者バランス戦略から選択できます: simple
、auto
、false
。simple
戦略は、受信したジョブを作業者プロセス間で均等に分配します:
'balance' => 'simple',
auto
戦略は、設定ファイルのデフォルトであり、キューの現在の負荷に基づいてキューごとの作業者プロセスの数を調整します。たとえば、notifications
キューに 1,000 件の保留中のジョブがあり、render
キューが空である場合、Horizon は 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 プロセスを一時停止し、horizon:pause
および horizon:continue
Artisan コマンドを使用してジョブの処理を続行するよう指示できます:
php artisan horizon:pause
php artisan horizon:continue
特定の Horizon スーパーバイザー を horizon:pause-supervisor
および horizon:continue-supervisor
Artisan コマンドを使用して一時停止および続行することもできます:
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1
Horizon プロセスの現在の状態を horizon:status
Artisan コマンドを使用して確認できます:
php artisan horizon:status
Horizon プロセスを優雅に終了するには、horizon:terminate
Artisan コマンドを使用します。現在処理中のジョブは完了し、その後 Horizon の実行が停止します:
php artisan horizon:terminate
Horizon のデプロイ
Horizon をアプリケーションの実際のサーバーにデプロイする準備ができたら、プロセスモニターを設定して php artisan horizon
コマンドを監視し、予期せず終了した場合に再起動するようにします。心配しないでください。プロセスモニターのインストール方法については、以下で説明します。
アプリケーションのデプロイプロセス中に、Horizon プロセスを終了するよう指示し、プロセスモニターによって再起動され、コード変更を受け取るようにします:
php artisan horizon:terminate
スーパーバイザーのインストール
スーパーバイザーは Linux オペレーティングシステム用のプロセスモニターであり、実行が停止した場合に自動的に horizon
プロセスを再起動します。Ubuntu にスーパーバイザーをインストールするには、次のコマンドを使用できます。Ubuntu を使用していない場合は、オペレーティングシステムのパッケージマネージャーを使用してスーパーバイザーをインストールできる可能性があります:
sudo apt-get install supervisor
スーパーバイザーを自分で設定するのが大変に感じる場合は、Laravel Forge を使用することを検討してください。これにより、Laravel プロジェクト用にスーパーバイザーが自動的にインストールおよび設定されます。
スーパーバイザー設定
スーパーバイザーの設定ファイルは通常、サーバーの /etc/supervisor/conf.d
ディレクトリ内に保存されます。このディレクトリ内で、スーパーバイザーがプロセスをどのように監視するかを指示する任意の数の設定ファイルを作成できます。たとえば、horizon.conf
ファイルを作成して horizon
プロセスを開始および監視しましょう:
[program:horizon]
process_name=%(program_name)s
command=php /home/forge/example.com/artisan horizon
autostart=true
autorestart=true
user=forge
redirect_stderr=true
stdout_logfile=/home/forge/example.com/horizon.log
stopwaitsecs=3600
スーパーバイザーの設定を定義する際は、stopwaitsecs
の値が最も長く実行されるジョブによって消費される秒数より大きいことを確認してください。そうしないと、スーパーバイザーがジョブを処理が完了する前に終了させる可能性があります。
上記の例は Ubuntu ベースのサーバーに有効ですが、スーパーバイザーの設定ファイルに期待される場所やファイル拡張子は、他のサーバーオペレーティングシステムによって異なる場合があります。詳細については、サーバーのドキュメントを参照してください。
スーパーバイザーの起動
設定ファイルが作成されたら、次のコマンドを使用してスーパーバイザーの設定を更新し、監視されるプロセスを起動できます:
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
スーパーバイザーの実行に関する詳細は、スーパーバイザーのドキュメント を参照してください。
タグ
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
{
// ...
}
}
このジョブが App\Models\Video
インスタンスと共にキューに入れられ、id
属性が 1
の場合、自動的に 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];
}
}
通知
Horizon を Slack や SMS 通知を送信するように設定する際は、関連する通知チャネルの 前提条件 を確認してください。
キューの待機時間が長い場合に通知を受け取りたい場合は、Horizon::routeMailNotificationsTo
、Horizon::routeSlackNotificationsTo
、および Horizon::routeSmsNotificationsTo
メソッドを使用できます。これらのメソッドは、アプリケーションの App\Providers\HorizonServiceProvider
メソッドから呼び出すことができます:
/**
* Bootstrap any application services.
*/
public function boot(): void
{
parent::boot();
Horizon::routeSmsNotificationsTo('15556667777');
Horizon::routeMailNotificationsTo('');
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