イントロダクション
Note: Laravel Horizonを掘り下げる前に、Laravelの基本的なキューサービスをよく理解しておく必要があります。Horizonは、Laravelが提供する基本的なキュー機能にまだ慣れていない場合は混乱してしまう可能性がある追加機能であり、Laravelのキューを拡張します。
Laravel Horizonは、Laravelを利用したRedisキューに美しいダッシュボードとコード駆動型の設定を提供します。Horizonを使用すると、ジョブのスループット、ランタイム、ジョブの失敗など、キューシステムの主要なメトリックを簡単に監視できます。
Horizonを使用する場合、すべてのキューワーカ設定は単一の単純な設定ファイルへ保存します。バージョン管理されたファイルでアプリケーションのワーカ設定を定義することにより、アプリケーションのデプロイ時に、キューワーカを簡単にスケーリングや変更できます。
インストール
Warning!! 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
へ設置されます。この設定ファイルでアプリケーションのキューワーカオプションを設定できます。各設定オプションにはその目的の説明が含まれているため、このファイルを徹底的に調べてください。
Warning!! 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,
],
],
],
Horizonを起動すると、アプリケーションを実行する環境のワーカープロセス設定オプションが使用されます。通常、環境はAPP_ENV
環境変数の値によって決定されます。たとえば、デフォルトのlocal
Horizon環境は、3つのワーカープロセスを開始し、各キューに割り当てられたワーカプロセスの数のバランスを自動的にとるように設定されています。デフォルトのproduction
環境は、最大10個のワーカプロセスを開始し、各キューに割り当てられたワーカプロセスの数のバランスを自動的にとるように設定されています。
Warning!!
horizon
設定ファイルのenvironments
部分に、Horizonを実行する予定の各環境のエントリを確実に指定してください。
スーパーバイザ
Horizonのデフォルトの設定ファイルでわかるように。各環境には、1つ以上の「スーパーバイザ(supervisor)」を含めることができます。デフォルトでは、設定ファイルはこのスーパーバイザをsupervisor-1
として定義します。ただし、スーパーバイザには自由に名前を付けることができます。各スーパーバイザは、基本的にワーカプロセスのグループを「監視」する責任があり、キュー間でワーカプロセスのバランスを取ります。
特定の環境で実行する必要があるワーカプロセスの新しいグループを定義する場合は、指定環境にスーパーバイザを追加します。アプリケーションが使用する特定のキューへ他のバランス戦略やワーカープロセス数を指定することもできます。
デフォルト値
Horizonのデフォルト設定ファイル内に、defaults
設定オプションがあります。この設定オプションにアプリケーションのスーパーバイザのデフォルト値を指定します。スーパーバイザのデフォルト設定値は、各環境のスーパーバイザの設定にマージされるため、スーパーバイザを定義するときに不必要な繰り返しを回避できます。
バランス戦略
Laravelのデフォルトのキューシステムとは異なり、Horizonでは3つのワーカーバランス戦略(simple
、auto
、false
)から選択できます。設定ファイルのデフォルトであるsimple
戦略は、受信ジョブをワーカープロセス間で均等に分割します。
'balance' => 'simple',
auto
戦略は、キューの現在のワークロードに基づいて、キューごとのワーカープロセスの数を調整します。たとえば、render
キューが空のときにnotifications
キューに1,000の保留中のジョブがある場合、Horizonはキューが空になるまでnotifications
キューにさらに多くのワーカを割り当てます。
auto
戦略を使用する場合、minProcesses
およびmaxProcesses
設定オプションを定義して、Horizonがスケールアップおよびスケールダウンするワーカープロセスの最小数と最大数を制御します。
'environments' => [
'production' => [
'supervisor-1' => [
'connection' => 'redis',
'queue' => ['default'],
'balance' => 'auto',
'minProcesses' => 1,
'maxProcesses' => 10,
'balanceMaxShift' => 1,
'balanceCooldown' => 3,
'tries' => 3,
],
],
],
balanceMaxShift
とbalanceCooldown
の設定値は、Horizonがワーカの需要を満たすためにどれだけ迅速にスケーリングするかを決定します。上記の例では、3秒ごとに最大1つの新しいプロセスが作成または破棄されます。アプリケーションのニーズに基づいて、必要に応じてこれらの値を自由に調整できます。
balance
オプションをfalse
に設定している場合、デフォルトのLaravel動作が使用され、設定にリストされている順序でキューを処理します。
ダッシュボードの認可
Horizonは、/horizon
のURIでダッシュボードを公開します。デフォルトでは、このダッシュボードにアクセスできるのはlocal
環境のみです。ただし、app/Providers/HorizonServiceProvider.php
ファイル内には、認可ゲートの定義があります。この認証ゲートは、非ローカル環境でのHorizonへのアクセスを制御します。必要に応じてこのゲートを自由に変更して、Horizonインストールへのアクセスを制限できます。
/**
* Horizonゲートの登録
*
* このゲートは、非ローカル環境で誰がHorizonにアクセスできるかを決定します。
*
* @return void
*/
protected function gate()
{
Gate::define('viewHorizon', function ($user) {
return in_array($user->email, [
'taylor@laravel.com',
]);
});
}
その他の認証戦略
Laravelは認証済みユーザーをゲートクロージャへ自動的に依存挿入することを忘れないでください。アプリケーションがIP制限などの別の方法でHorizonセキュリティを提供する場合、Horizonユーザーは「ログイン」する必要がない場合もあります。したがって、Laravelの認証を必要としないようにするには、上記のfunction($user)
クロージャ引数をfunction($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 Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
// ...
}
Horizonのアップグレード
Horizonの新しいメジャーバージョンにアップグレードするときは、アップグレードガイドを注意深く確認することが重要です。さらに、新しいHorizonバージョンにアップグレードするときは、Horizonのアセットを再公開する必要があります。
php artisan horizon:publish
アセットを最新の状態に保ち、将来の更新で問題が発生しないようにするには、アプリケーションのcomposer.json
ファイルのpost-update-cmd
スクリプトに、vendor:publish --tag=laravel-assets
コマンドを追加します。
{
"scripts": {
"post-update-cmd": [
"@php artisan vendor:publish --tag=laravel-assets --ansi --force"
]
}
}
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
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設定を更新し、監視対象プロセスを開始できます。
sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start horizon
Note: 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;
/**
* Videoインスタンス
*
* @var \App\Models\Video
*/
public $video;
/**
* 新しいジョブインスタンスの生成
*
* @param \App\Models\Video $video
* @return void
*/
public function __construct(Video $video)
{
$this->video = $video;
}
/**
* ジョブの実行
*
* @return void
*/
public function handle()
{
//
}
}
このジョブが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);
ジョブに手作業でタグ付ける
Queueableオブジェクトの1つにタグを手作業で定義する場合は、クラスにtags
メソッドを定義します。
class RenderVideo implements ShouldQueue
{
/**
* ジョブに割り当てるタグを取得
*
* @return array
*/
public function tags()
{
return ['render', 'video:'.$this->video->id];
}
}
通知
Warning!! SlackまたはSMS通知を送信するようにHorizonを設定する場合は、関連する通知チャネルの前提条件を確認する必要があります。
キューの1つに長い待機時間があったときに通知を受け取りたい場合は、Horizon::routeMailNotificationsTo
、Horizon::routeSlackNotificationsTo
、およびHorizon::routeSmsNotificationsTo
メソッドが使用できます。これらのメソッドは、アプリケーションのApp\Providers\HorizonServiceProvider
のboot
メソッドから呼び出せます。
/**
* 全アプリケーションサービスの初期起動処理
*
* @return void
*/
public function boot()
{
parent::boot();
Horizon::routeSmsNotificationsTo('15556667777');
Horizon::routeMailNotificationsTo('example@example.com');
Horizon::routeSlackNotificationsTo('slack-webhook-url', '#channel');
}
待機通知の時間のしきい値の設定
アプリケーションのconfig/horizon.php
設定ファイル内で「長時間待機」と見なす秒数を設定できます。このファイル内のwaits
設定オプションを使用すると、各接続/キューの組み合わせの長時間待機しきい値を制御できます。
'waits' => [
'redis:default' => 60,
'redis:critical,high' => 90,
],
メトリクス
Horizonには、ジョブとキューの待機時間とスループットに関する情報を提供するメトリックダッシュボードが含まれています。このダッシュボードにデータを表示するには、アプリケーションのスケジューラで5分ごとにHorizonのsnapshot
Artisanコマンドを実行するように設定する必要があります。
/**
* アプリケーションのコマンドスケジュールの定義
*
* @param \Illuminate\Console\Scheduling\Schedule $schedule
* @return void
*/
protected function schedule(Schedule $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