設定
Laravelのキューコンポーネントは、様々なキューサービス共通のAPIを提供しています。キューによりメール送信のような時間を費やす処理を夜中まで遅らせることが可能です。これによりアプリケーションのリクエストを徹底的に引き上げることができます。
キューの設定ファイルはconfig/queue.php
です。このファイルには、フレームワークに含まれているそれぞれのドライバーへの接続設定があります。それには、データベース、Beanstalkd、IronMQ、Amazon SQS、Redis、null、同期(ローカル用途)ドライバーが含まれています。null
キュードライバーはキューされたジョブが実行されないように、破棄するだけです。
データベースキューテーブル
database
キュードライバーを使用するには、ジョブを記録するためのデータベーステーブルが必要です。このテーブルを作成するマイグレーションは、queue:table
Artisanコマンドにより生成できます。
php artisan queue:table
キューに必要なパッケージ
前記のキュードライバーを使用するには、以下の対応するパッケージをcomposer.jsonに付け加えることが必要です。
- Amazon SQS:
aws/aws-sdk-php
- Beanstalkd:
pda/pheanstalk ~3.0
- IronMQ:
iron-io/iron_mq ~1.5
- Redis:
predis/predis ~1.0
基本的な使用法
キューへジョブ登録
アプリケーションにキュー投入できる全ジョブはApp\Commands
ディレクトリーに保存します。新しいキュー投入コマンドを生成するには、Artisan
CLIコマンドを使用します。
php artisan make:command SendEmail --queued
新しいジョブをキューに投入するには、Queue::push
メソッドを使用します。
Queue::push(new SendEmail($message));
注目: この例では、
Queue
ファサードを直接使用しています。しかし、通常キューコマンドをディスパッチするには、コマンドバスの方が好まれます。このページでは、以降も続けてQueue
ファサードを使用しますが、アプリケーション上でキューと同期コマンドの両方を起動することができますので、コマンドバスにも習熟してください。
make:command
Artisanコマンドのデフォルトは、「自己処理」コマンドを生成します。つまり、handle
メソッドがコマンド自身へ含まれています。このメソッドはキューにより、ジョブが実行されるときに呼び出されます。handle
メソッドには必要な依存をタイプヒントで指定でき、サービスコンテナが自動的に注入します。
public function handle(UserRepository $users)
{
//
}
コマンドから独立したハンドラークラスを持たせたい場合は、--handler
フラッグをmake:command
コマンドに付けます。
php artisan make:command SendEmail --queued --handler
生成されるハンドラーは、App\Handlers\Commands
に置かれ、IoCコンテナにより依存解決されます。
ジョブのキューを指定
どのキューにジョブを登録するのかを指定することもできます。
Queue::pushOn('emails', new SendEmail($message));
同一データ本体の複数ジョブ投入
同じデーターを複数のキュージョブに送る必要がある場合は、Queue::bulk
メソッドを使用して下さい。
Queue::bulk([new SendEmail($message), new AnotherCommand]);
ジョブ実行の遅延
キュージョブの実行を遅らせたい場合もあるでしょう。例えば、サインアップの15分後に顧客へメールを送信するジョブをキューしたい場合などです。この場合、Queue::later
メソッドを使用して下さい。
$date = Carbon::now()->addMinutes(15);
Queue::later($date, new SendEmail($message));
この例の中で、ジョブに希望する遅延実行時間を指定するために、Carbonライブラリーを使用しています。もしくは、整数で遅らせたい秒数を渡すこともできます。
注目: Amazon SQSサービスには、遅延900秒(15分)という制限があります。
キューとEloquentモデル
もし、キュージョブがコンストラクターにEloquentモデルを受け付ける場合、そのモデルのIDだけがキューへシリアライズされます。実際にそのジョブが処理される時に、キューシステムはデータベースからモデルの完全なインスタンスを自動的に再取得します。これにより、Eloquentのモデルインスタンスを完全にシリアライズすると持ち上がる問題を防ぐことができ、アプリケーションに対する完全な透過性も保てます。
処理済みのジョブの削除
ジョブを処理し終えた時、キューから削除する必要があります。ジョブの実行中に例外が投げられなければ、これは自動的に行われます。
ジョブを自分でdelete
やrelease
したければ、Illuminate\Queue\InteractsWithQueue
トレイトが提供するrelease
とdelete
メソッドで行えます。release
メソッドは引数をひとつだけ取り、再度実行するまでに待つ秒数を指定します。
public function handle(SendEmail $command)
{
if (true)
{
$this->release(30);
}
}
ジョブのキュー再投入
処理中に例外が投げられると、再実行できるよう自動的にキューに戻されます。アプリケーションで許可されている最高実行回数まで、そのジョブは繰り返されます。最高実行回数は、queue:listen
とqueue:work
Artisanコマンドへ、--tries
スイッチにより指定されます。
実行回数の取得
ジョブの処理中に例外が起きた場合、そのジョブは自動的にキューに再登録されます。そのジョブを実行しようとした試行回数をattempts
メソッドで調べることができます。
if ($this->attempts() > 3)
{
//
}
注目: このメソッドを呼び出すには、
Illuminate\Queue\InteractsWithQueue
トレイトを使用する必要があります。
クロージャーのキュー
もしくはキューにクロージャーを登録することも可能です。これは手軽にシンプルなタスクをキュー登録する必要がある場合に大変便利です。
キューのクロージャー登録
Queue::push(function($job) use ($id)
{
Account::delete($id);
$job->delete();
});
注目:
use
を使用し、キューするクロージャーでオブジェクトを使用できるように渡す代わりに主キーを渡し、キュージョブの中で関連するモデルを再取得する設計をしてください。これにより、シリアライズの予期しない影響を防ぐことができます。
Iron.ioのPushキューを利用する場合、キューのクロージャーで追加の予防策を取る必要があります。キューメッセージを受け取った時点でそのキューが本当にIron.ioからのリクエストであるかをチェックしてください。例えば、Pushキューの受け取りURLをhttps:://yourapp.com/queue/receive?token=秘密のトークン
のような形式で登録します。次に、キューリクエストでmarshalメソッドを実行する前に、秘密のトークンの値をアプリケーションでチェックします。
キューリスナーの実行
LaravelのArtisanは、新しくキューに保存されたジョブを実行するコマンドを含んでいます。queue:listen
コマンドで、このタスクを実行できます。
キューリスナーの開始
php artisan queue:listen
リスナーに使用するキュー接続を指定することもできます。
php artisan queue:listen connection
このタスクを一度開始したら、手動で停止しない限り実行を続けることに注意してください。Supervisorのようなプロセスモニターを利用し、キューリスナーが確実に動作し続けるようにしてください。
listen
コマンドにキューのプライオリティーを設定するため、キュー接続をカンマ区切りで指定することもできます。
php artisan queue:listen --queue=high,low
この例で、high-connection
はlow-connection
のジョブを実行する前にいつも処理されます。
ジョブのタイムアウト時間を指定する
それぞれのジョブの実行時間を秒数で指定することもできます。
php artisan queue:listen --timeout=60
キューのスリープ時間を指定する
さらに、新しいジョブをポーリングする前に、待ち秒数を指定することもできます。
php artisan queue:listen --sleep=5
キューにジョブがない場合のみ、キューがスリープすることに注意して下さい。もし、ジョブが存在しているなら、キューはスリープせずに処理を続けます。
キューの最初のジョブを実行する
キューの最初のジョブだけを実行するには、queue:work
コマンドを使用してください。
php artisan queue:work
デーモンキューワーカー
queue:work
はフレームワークを再起動せずに連続してジョブを処理し続けるように、キューワーカーを強制するための、--daemon
オプションも備えています。これにより、queue:listen
と比較すると、CPU使用率を大幅に引き下げることができますが、デプロイ中は現在実行中のジョブのキューを空にするために、複雑な手順の追加が必要になります。
キュー・ワーカーをデーモンモードで開始するためには、--daemon
フラッグを使用します。
php artisan queue:work connection --daemon
php artisan queue:work connection --daemon --sleep=3
php artisan queue:work connection --daemon --sleep=3 --tries=3
ご覧の通り、queue:work
コマンドはqueue:listen
で使用できるものと、ほぼ同じオプションをサポートしています。php artisan help queue:work
コマンドで全オプションを表示できます。
デーモンキューワーカーによるデプロイ
アプリケーションをデーモン・キュー・ワーカーでデプロイする、一番簡単な方法は、デプロイを開始するときに、アプリケーションをメンテナンスモードにすることです。php artisan down
コマンドにより切り替えられます。アプリケーションをメンテナンスモードにすると、Laravelは新しいジョブをキューに受け付けなくなりますが、存在しているジョブの処理は続けます。
ワーカーを一番簡単に再起動するには、デプロイスクリプトの中に、次のコマンドを含めてください。
php artisan queue:restart
このコマンドは、現在のジョブの処理が終了した後、全キューワーカーを再起動するように指示します。
注意: このコマンドは再起動のスケジュールするため、キャッシュシステムを利用しています。デフォルト状態では、APCuはCLIコマンドのために動作しません。APCuを使用する場合、
apc.enable_cli=1
をAPCu設定に追加してください。
デーモンキューワーカーのコーディング
デーモンキューワーカーは、各ジョブを処理する前にフレームワークを再起動しません。そのため、多くのリソースを使用するジョブを完了する前に、それらを開放するように気をつけてください。例えば、GDライブラリーを使用し、画像処理を行う場合、完了したらimagedestroy
でメモリを開放する必要があるでしょう。
同様に、デーモンが長時間動作し、使用され続ければデータベース接続は切断されるでしょう。新しい接続を行うために、DB::reconnect
メソッドを使う必要が起きるでしょう。
Pushキュー
デーモンやバックグラウンドリスナーを走らせなくても、Pushキューを使えばLaravel5のキュー機能を存分に利用できます。現在、PushキューはIron.ioドライバーでしかサポートされていません。開始する前にIron.ioのアカウントを作成し、Ironの認証データーをconfig/queus.php
設定ファイルに追加してください。
Pushキュー購読の登録
次に、新しく登録されたキュージョブを受け取るエンドポイントURLをqueue::subscribe
Artisanコマンドで登録します。
php artisan queue:subscribe queue_name queue/receive
php artisan queue:subscribe queue_name http://foo.com/queue/receive
これでIronダッシュボードへログインすると、新しいPushキューが購読URLと共に表示されます。指定したキューに対し、好きなだけURLを購読することもできます。次に、queue/receive
エンドポイントへのルートを生成し、Queue::marshal
メソッドからのレスポンスをリターンしてください。
Route::post('queue/receive', function()
{
return Queue::marshal();
});
marshal
メソッドは正しいジョブハンドラークラスが実行されるように取り計らいます。Pushキューへのジョブを実行するには、Queue::push
メソッドと同様にキューの使用手順に従い利用してください。
失敗したジョブ
物事はうまく行かない場合もありますので、キュージョブが失敗することも想定できます。でも、心配ありません。最高な人たちも失敗はするものです!
Laravelは指定した回数ジョブを再実行する便利な方法を用意しています。この回数実行してもうまく行かない場合は、faild_jobs
テーブルに登録されます。この失敗したジョブのテーブル名は、config/queue.php
設定ファイルで指定できます。
faild_jobs
テーブルのマイグレーションを生成するには、queue:faild-table
コマンドを実行して下さい。
php artisan queue:failed-table
ジョブ再実行の最大回数を指定するには、queue:listen
コマンドに--tries
スイッチを付け実行して下さい。
php artisan queue:listen connection-name --tries=3
キュージョブが失敗した時に呼び出されるイベントのリスナーを登録したい場合は、Queue::failing
メソッドを使って下さい。このイベントは、メールかHipChatであなたのチームに通知するために便利でしょう。
Queue::failing(function($connection, $job, $data)
{
//
});
キュージョブクラスへ直接failed
メソッドを定義すると、失敗が起きたときに指定されたアクションが実行されるようになります。
public function failed()
{
// ジョブが失敗した時に呼ばれる…
}
失敗したジョブの再実行
失敗したジョブを全部確認するには、queue:failed
Arisanコマンドを利用します。
php artisan queue:failed
queue:failed
コマンドにジョブIDを指定すれば、接続、キュー、失敗した時間がリストされます。ジョブIDは失敗したジョブを再実行する場合にも使用します。例えば、IDが5の失敗したジョブを再実行するには、以下のコマンドを実行します。
php artisan queue:retry 5
失敗したジョブを削除するには、queue:forget
コマンドを使います。
php artisan queue:forget 5
失敗したジョブを全部消去するには、queue:flush
コマンドを使用します。
php artisan queue:flush