メインコンテンツまでスキップ

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 を実行する環境ごとに、horizon 設定ファイルの environments 部分に実行する 環境 ごとのエントリが含まれていることを確認してください。

スーパーバイザー

Horizonのデフォルト構成ファイルで確認できるように、各環境には1つ以上の「スーパーバイザー」が含まれることがあります。デフォルトでは、構成ファイルではこのスーパーバイザーを supervisor-1 と定義していますが、自由にスーパーバイザーの名前を付けることができます。各スーパーバイザーは基本的に、ワーカープロセスのグループを「監督」し、ワーカープロセスをキュー全体でバランスよく配置する役割を担います。

特定の環境に追加のスーパーバイザーを追加することができます。これにより、その環境で実行する新しいワーカープロセスのグループを定義することができます。アプリケーションで使用するキューごとに異なるバランス戦略やワーカープロセス数を定義したい場合にこれを行うことができます。

メンテナンスモード

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

    'environments' => [
'production' => [
'supervisor-1' => [
// ...
'force' => true,
],
],
],

デフォルト値

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

バランス戦略

Laravelのデフォルトキューシステムとは異なり、Horizonでは3つのワーカーバランス戦略から選択できます: simpleauto、および falsesimple 戦略は、ジョブを均等にワーカープロセス間で分割します。

    'balance' => 'simple',

auto 戦略は、構成ファイルのデフォルトであり、キューの現在のワークロードに基づいてキューごとのワーカープロセス数を調整します。たとえば、notifications キューに 1,000 の保留中のジョブがある場合、render キューが空である場合、Horizonは notifications キューに対してワーカーを追加し、キューが空になるまで追加します。

使用auto策略时,您可以定义minProcessesmaxProcesses配置选项,以控制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策略)来分配更多的工作进程。

balanceMaxShiftbalanceCooldown配置值确定Horizon将如何快速扩展以满足工作进程需求。在上面的示例中,每三秒钟最多会创建或销毁一个新进程。您可以根据应用程序的需求自由调整这些值。

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 Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

// ...
}

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: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プロジェクト用に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がジョブを処理が完了する前に終了させる可能性があります。

警告

上記の例は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\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;

class RenderVideo implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

/**
* 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::routeMailNotificationsToHorizon::routeSlackNotificationsToHorizon::routeSmsNotificationsTo メソッドを使用できます。これらのメソッドは、アプリケーションの App\Providers\HorizonServiceProviderboot メソッドから呼び出すことができます。

    /**
* 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 を唯一の引数として受け入れます:

php artisan horizon:forget 5

キューからジョブをクリアする

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

php artisan horizon:clear

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

php artisan horizon:clear --queue=emails