Laravelのキューサービス
Laravelのキューサービスは、Amazon SQS、Redis、さらにはリレーショナル・データベースなどさまざまなキューバックエンドに対し共通のAPIを提供しています。キューによりメール送信のような時間を費やす処理を遅らせることが可能です。時間のかかるタスクを遅らせることで、よりアプリケーションのリクエストをスピードアップさせます。
Queueドライバー
データベース
データベースキュードライバーを使用するには、ジョブを記録するためのテーブルを用意する必要があります。
queue:tableコマンドで簡単に生成できます。
php artisan queue:table
php artisan migrate
.envのQUEUE_CONNECTION
をdatabase
に変更してください。
Redis
Redisをドライバーに用いるためには、Redisのデータベースを設定する必要があります。
dockerでRedisのコンテナを作成するには、以下が参考になりました。
https://zenn.dev/marushin/articles/4903cd0bbbcee0
.envのQUEUE_CONNECTION
をredis
に変更してください。
Jobクラスの作成
Jobクラスは、非同期処理を行うためのクラスです。
全てのジョブは、デフォルトでapp/Jobsに生成されます。
php artisan make:job {クラス名}
で簡単にJobクラスを生成することができます。
<?php
namespace App\Jobs;
use App\AudioProcessor;
use App\Podcast;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
class ProcessPodcast implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $podcast;
/**
* 新しいジョブインスタンスの生成
*
* @param Podcast $podcast
* @return void
*/
public function __construct(Podcast $podcast)
{
$this->podcast = $podcast;
}
/**
* ジョブの実行
*
* @param AudioProcessor $processor
* @return void
*/
public function handle(AudioProcessor $processor)
{
// ジョブが実行される際に呼び出される処理…
}
}
上記が生成されたJobクラスです。
この中のhandle
メソッド内が、キューによってジョブが実行される際に呼び出されます。
Jobを呼び出す(ディスパッチ)
dispatch
ジョブクラス自身のdispatch
メソッドを使い。ジョブを実行させます。dispatch
メソッドへ渡す引数は、ジョブのコンストラクタへ渡されます。
class PodcastController extends Controller
{
/**
* 新ポッドキャストの保存
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// ポッドキャスト作成…
ProcessPodcast::dispatch($podcast);
}
}
dipatchIf・dipatchUnless
条件によりジョブをディスパッチする場合は、dispatchIf
かdispatchUnless
を使います
第一引数に条件、それ以降にJobクラスのコンストラクタに渡す値を設定します。
ProcessPodcast::dispatchIf($accountActive === true, $podcast);
ProcessPodcast::dispatchUnless($accountSuspended === false, $podcast);
遅延ディスパッチ
ジョブの実行を遅らせたい場合は、ジョブのディスパッチ時にdelay
メソッドを使います。
この例では、5分後に処理を行うように設定しています。
ProcessPodcast::dispatch($podcast)
->delay(now()->addMinutes(5));
dispatchAfterResponse
ユーザーにレスポンスを送った後に実行されるdispatchAfterResponse
メソッドがあります。
dispatchNow
ジョブを非同期でなく、同期的に実行させたい場合は、dispatchNow
メソッドを使用します。
キューを用いたカテゴライズ。
ジョブを異なるキューへ投入することで「カテゴライズ」できます。
dispatchメソッドの後にonQueueメソッドを付けることによってカテゴライズします。
ProcessPodcast::dispatch($podcast)->onQueue('processing');
ワークプロセスの実行
キューに貯められたジョブを実行するには、queue:work
プロセスを実行する必要があります。
queue:workコマンドが起動したら、手動で停止するか、ターミナルを閉じるまで実行し続けることに注意してください。
php artisan queue:work
最大時効回数の設定
ジョブが試行する最大回数を指定するには、--tries
スイッチを使用します。
または、ジョブクラスに、$tries
を定義することで設定することも可能です。
タイムアウトの設定
ジョブの最大実行秒数を指定するために、--timeoutスイッチを使用します。
php artisan queue:work --tiimeout=30
または、ジョブクラスに、$timeout
を定義することで設定することも可能です。
再試行までの時間の設定
失敗してから再試行するまでに何秒待てばよいかを指定するために、--delayスイッチを使用します。
この場合、処理が失敗してから30秒後に再試行します。
php artisan queue:work --tries_3 --delay =30
または、ジョブクラスに、$retryAfter
を定義することで設定することも可能です。
queue:listen
queue:work
以外でジョブを実行させる以外に、queue:listen
コマンドを使用することもできます。
queue:listen
コマンドを使えば更新したコードを読み込みたい場合に、手動でワーカをリスタートする必要がなくなります。
しかし、動作のスピードがqueue:workより悪くなってしますデメリットもあります。
queueを指定する
指定した接続の特定のキューだけを処理するように、さらにキューワーカをカスタマイズすることもできます。
php artisan --queue=upload
この場合、dispatch()->onQueue('upload')
でディスパッチしたジョブのみが実行されます。
キューのデプロイ
キューワーカは長時間起動プロセスであるため、リスタートしない限りコードの変更を反映しません。キューを使用しているアプリケーションのコードの変更を取り込む簡単な方法は、ワーカをリスタートすることです。queue:restart
コマンドを実行することで、全ワーカーを再起動できます。
php artisan queue:restart
失敗したジョブ
失敗したジョブは、fialed_job
テーブルに挿入されます。
こちらも、queue:failed-table
コマンドで簡単に作成できます。
php artisan queue:failed-table
php artisan migrate
失敗した時の処理を書く
ジョブクラスにfailed
メソッドを定義すると、ジョブが失敗したときにfailed
メソッド内で書かれた処理が実行されます。
public function failed(Throwable $exception)
{
// 失敗の通知をユーザーへ送るなど…
}
Supervisor設定
Supervisorを設定することで、workerプロセスを永続化させることができます。
設定方法は、自分が作成した以下のリンクから確認してください!
https://qiita.com/RyujiWatanabe/items/f4b132a9107bf8ba5f4e