Amazon SQSを使ったLaravelメールキューを実装する
Laravelを使ったとあるWEBシステムに、メール送信機能を実装しました。このシステムでは、メールを一括送信する要件があったため、メール送信部分は非同期で実装しました。
Laravelでは、タスクをバックグラウンドで処理させる仕組みとして「キュー」が存在します。Laravelキューは、データベース、Amazon SQS、Redisといったドライバをサポートしていますが、今回はAmazon SQSの「FIFOキュー」を利用して実装しました。
この記事では、Amazon SQSを用いたメールキューの実装方法をまとめています。
動作環境
- Laravel 7.0
aws/aws-sdk-php
を導入済み- メール送信機能を実装済み
- Amazon SQSのFIFOキューを準備済み
実装
1. キューにメッセージを送るサービスを作成
SqsFifoQueue.php
<?php
namespace App\Services;
use Illuminate\Queue\SqsQueue;
class SqsFifoQueue extends SqsQueue
{
public function pushRaw($payload, $queue = null, $options = [])
{
$response = $this->sqs->sendMessage([
'QueueUrl' => $this->getQueue($queue),
'MessageBody' => $payload,
'MessageGroupId' => uniqid(),
'MessageDeduplicationId' => uniqid(),
]);
return $response->get('MessageId');
}
}
2. キューに接続するサービスを作成
SqsFifoConnector.php
<?php
namespace App\Services;
use Aws\Sqs\SqsClient;
use Illuminate\Support\Arr;
use Illuminate\Queue\Connectors\SqsConnector;
class SqsFifoConnector extends SqsConnector
{
public function connect($config)
{
$config = $this->getDefaultConfiguration($config);
if ($config['key'] && $config['secret']) {
$config['credentials'] = Arr::only($config, ['key', 'secret']);
}
return new SqsFifoQueue(new SqsClient($config), $config['queue']);
}
}
3. キュー接続用のサービスプロバイダを作成
SqsFifoServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\SqsFifoConnector;
class SqsFifoServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->afterResolving('queue', function ($manager) {
$manager->addConnector('sqsfifo', function () {
return new SqsFifoConnector;
});
});
}
}
config/app.php
return [
'providers' => [
App\Providers\SqsFifoServiceProvider::class,
],
];
4. キューの接続情報を追加
config/queue.php
return [
'connections' => [
'sqsfifo' => [
'driver' => 'sqsfifo',
'key' => env('AWS_QUEUE_ACCESS_KEY_ID'),
'secret' => env('AWS_QUEUE_SECRET_ACCESS_KEY'),
'queue' => env('SQS_QUEUE'),
'region' => env('AWS_DEFAULT_REGION'),
],
],
];
5. 環境変数を追加
.env
# 変更
QUEUE_CONNECTION=sqsfifo
# 新規追加
AWS_QUEUE_ACCESS_KEY_ID=<[KEY_ID]>
AWS_QUEUE_SECRET_ACCESS_KEY=<[SECRET_KEY]>
SQS_QUEUE=<[END_POINT]>
AWS_DEFAULT_REGION=<[REGION]>
6. ジョブクラスの作成
SendSampleMail.php
<?php
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Mail;
use App\Mail\SampleMail;
class SendSampleMail implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $tries = 3; // 処理失敗時の最大試行回数
public $data;
public function __construct(array $data)
{
$this->data = $data;
}
public function handle()
{
Mail::to('<[YOUR_ADDRESS]>')->send(new SampleMail(
$this->data,
));
}
}
7. メール送信部分を修正
実装済みのメール送信部分をdispatch()
に置き換えます。
SampleController.php
<?php
namespace App\Http\Controllers;
class SampleController extends Controller
{
public function index(Request $request)
{
// Mail::to('<[YOUR_ADDRESS]>')->send(new SampleMail($request));
SendSampleMail::dispatch($request);
}
}
8. キューワーカーを起動して動作確認
php artisan queue:work
でキューワーカーを起動して、実際にメールを送信してみましょう。
Amazon SQSのモニタリング画面でレスポンスの返却が確認できればOKです。
所感
本番環境でキューサービスを利用する際は、Supervisorの導入が欠かせません。
こちらの記事でSupervisorの導入方法を説明しています。興味のある方はどうぞ。