Laravel Horizon¶
はじめに¶
Note
Laravel Horizonを掘り下げる前に、Laravelの基本キューサービスに慣れておくべきです。HorizonはLaravelのキューに追加機能を提供しますが、それらの機能はLaravelが提供する基本的なキュー機能に慣れていないと混乱するかもしれません。
Laravel Horizonは、Laravelが動作するRedisキューのための美しいダッシュボードとコード駆動の設定を提供します。Horizonを使用すると、ジョブのスループット、実行時間、ジョブの失敗など、キューシステムの主要なメトリクスを簡単に監視できます。
Horizonを使用すると、すべてのキューワーカーの設定が単一のシンプルな設定ファイルに保存されます。アプリケーションのワーカー設定をバージョン管理されたファイルで定義することで、アプリケーションをデプロイする際にキューワーカーを簡単にスケールまたは変更できます。
インストール¶
Warning
Laravel Horizonでは、キューを動作させるためにRedisを使用する必要があります。したがって、キュー接続がアプリケーションのconfig/queue.php
設定ファイルでredis
に設定されていることを確認してください。
Composerパッケージマネージャを使用して、プロジェクトにHorizonをインストールできます:
Horizonをインストールした後、horizon:install
Artisanコマンドを使用してそのアセットを公開します:
設定¶
Horizonのアセットを公開した後、その主要な設定ファイルはconfig/horizon.php
に配置されます。この設定ファイルでは、アプリケーションのキューワーカーオプションを設定できます。各設定オプションにはその目的の説明が含まれているため、このファイルを徹底的に確認してください。
Warning
Horizonは内部でhorizon
という名前のRedis接続を使用します。このRedis接続名は予約されており、database.php
設定ファイル内またはhorizon.php
設定ファイルのuse
オプションの値として別のRedis接続に割り当てるべきではありません。
環境¶
インストール後、主な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のワーカープロセスを開始し、各キューに割り当てられたワーカープロセスの数を自動的にバランスさせるように設定されています。
Warning
Horizonを実行する予定の各環境に対して、horizon
設定ファイルのenvironments
部分にエントリが含まれていることを確認する必要があります。
スーパーバイザ¶
Horizonのデフォルト設定ファイルでわかるように、各環境には1つ以上の「スーパーバイザ」を含めることができます。デフォルトでは、このスーパーバイザはsupervisor-1
として定義されています。ただし、スーパーバイザには自由に名前を付けることができます。各スーパーバイザは基本的にワーカープロセスのグループを「監視」し、ワーカープロセスをキュー間でバランスさせる役割を果たします。
特定の環境に追加のスーパーバイザを追加することができます。これは、その環境で実行される新しいワーカープロセスのグループを定義したい場合に行います。これを行う場合、アプリケーションが使用する特定のキューに対して異なるバランシング戦略またはワーカープロセス数を定義することができます。
メンテナンスモード¶
アプリケーションがメンテナンスモードにある間、キューに入れられたジョブはHorizonによって処理されません。ただし、スーパーバイザのforce
オプションがHorizon設定ファイル内でtrue
と定義されている場合を除きます:
'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がワーカーの需要に合わせてどれだけ迅速にスケールするかを決定します。上記の例では、最大で1つの新しいプロセスが3秒ごとに作成または破棄されます。アプリケーションのニーズに応じて、これらの値を自由に調整できます。
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, [
'taylor@laravel.com',
]);
});
}
代替認証戦略¶
Laravelは自動的に認証されたユーザーをゲートクロージャに注入することを覚えておいてください。アプリケーションがIP制限などの別の方法でHorizonのセキュリティを提供している場合、Horizonユーザーは「ログイン」する必要がないかもしれません。したがって、上記のfunction (User $user)
クロージャシグネチャをfunction (User $user = null)
に変更して、Laravelに認証を要求しないようにする必要があります。
サイレンスされたジョブ¶
時には、アプリケーションやサードパーティパッケージによってディスパッチされる特定のジョブを表示することに興味がない場合があります。これらのジョブが「完了したジョブ」リストにスペースを取らないように、それらをサイレンスすることができます。始めるには、ジョブのクラス名をアプリケーションの 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を起動できます。この単一のコマンドは、現在の環境に対して設定されたすべてのワーカープロセスを開始します。
horizon:pause
および horizon:continue
Artisanコマンドを使用して、Horizonプロセスを一時停止し、ジョブの処理を続行するように指示できます。
特定のHorizon スーパーバイザ を一時停止および続行するには、horizon:pause-supervisor
および horizon:continue-supervisor
Artisanコマンドを使用できます。
php artisan horizon:pause-supervisor supervisor-1
php artisan horizon:continue-supervisor supervisor-1
horizon:status
Artisanコマンドを使用して、Horizonプロセスの現在のステータスを確認できます。
horizon:terminate
Artisanコマンドを使用して、Horizonプロセスを正常に終了できます。現在処理中のジョブは完了し、その後Horizonは実行を停止します。
Horizonのデプロイ¶
Horizonをアプリケーションの実際のサーバーにデプロイする準備ができたら、php artisan horizon
コマンドを監視し、予期せず終了した場合に再起動するようにプロセスモニタを設定する必要があります。心配はいりません。以下でプロセスモニタのインストール方法について説明します。
アプリケーションのデプロイプロセス中に、Horizonプロセスに終了するように指示して、プロセスモニタによって再起動され、コードの変更を受け取るようにする必要があります。
Supervisorのインストール¶
SupervisorはLinuxオペレーティングシステムのプロセスモニタであり、horizon
プロセスが実行を停止した場合に自動的に再起動します。UbuntuにSupervisorをインストールするには、次のコマンドを使用できます。Ubuntu以外を使用している場合は、オペレーティングシステムのパッケージマネージャを使用してSupervisorをインストールできます。
Note
Supervisorの設定が難しいと感じる場合は、Laravel Forgeの使用を検討してください。これにより、Laravelプロジェクトに対して自動的にSupervisorがインストールおよび設定されます。
Supervisorの設定¶
Supervisorの設定ファイルは通常、サーバーの /etc/supervisor/conf.d
ディレクトリに保存されます。このディレクトリ内に、Supervisorにプロセスの監視方法を指示する任意の数の設定ファイルを作成できます。例えば、horizon
プロセスを開始および監視する horizon.conf
ファイルを作成しましょう。
[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
Supervisorの設定を定義する際に、stopwaitsecs
の値が最も長い実行ジョブによって消費される秒数よりも大きいことを確認する必要があります。そうしないと、Supervisorはジョブが処理を完了する前にジョブを強制終了する可能性があります。
Warning
上記の例はUbuntuベースのサーバーに有効ですが、Supervisor設定ファイルの場所と期待されるファイル拡張子は、他のサーバーオペレーティングシステムによって異なる場合があります。サーバーのドキュメントを参照して詳細を確認してください。
Supervisorの起動¶
設定ファイルが作成されたら、次のコマンドを使用してSupervisorの設定を更新し、監視対象のプロセスを開始できます。
Note
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モデルが見つかった場合、モデルのクラス名と主キーを使用してインテリジェントにジョブにタグ付けするためです。
use App\Jobs\RenderVideo;
use App\Models\Video;
$video = Video::find(1);
RenderVideo::dispatch($video);
ジョブの手動タグ付け¶
キュー可能なオブジェクトの1つに対して手動でタグを定義したい場合は、クラスに 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];
}
}
通知¶
Warning
Horizonを設定してSlackまたはSMS通知を送信する場合、関連する通知チャネルの前提条件を確認する必要があります。
キューの待ち時間が長い場合に通知を受け取りたい場合は、Horizon::routeMailNotificationsTo
、Horizon::routeSlackNotificationsTo
、および Horizon::routeSmsNotificationsTo
メソッドを使用できます。これらのメソッドは、アプリケーションの App\Providers\HorizonServiceProvider
の boot
メソッドから呼び出すことができます。
/**
* Bootstrap any application services.
*/
public function boot(): void
{
parent::boot();
Horizon::routeSmsNotificationsTo('15556667777');
Horizon::routeMailNotificationsTo('example@example.com');
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を引数として受け取ります。
失敗したすべてのジョブを削除したい場合は、horizon:forget
コマンドに --all
オプションを指定できます。
キューからジョブをクリアする¶
アプリケーションのデフォルトキューからすべてのジョブを削除したい場合は、horizon:clear
Artisanコマンドを使用できます。
特定のキューからジョブを削除するために、queue
オプションを指定することもできます。