PHPでSQSのFIFOキューを使った時のメモ
SQSのFIFOキューを使用する時に調べた事を記述します。
みんな大好きSQSは昔から存在する手軽に利用できるキューシステムですが、メッセージの順序保障と二重送信などはアプリ側で考慮する必要がありました。
しかし何時の間にやらFIFOキューとして機能が強化されていましたので調べてみた次第です
Amazon Simple Queue Service の新機能 – 1 回だけの処理と重複排除機能を備えた FIFO キュー | Amazon Web Services ブログ
※ただし、現在はUS East (Ohio) および US West (Oregon)でのみ利用可能な機能のようです。
まずはaws上で「オレゴン」リージョンにSQSのキューを作成します。
FIFOキューを選択肢します。
既にcomposerで以下のバージョンのawsのsdkを導入済とします
"aws/aws-sdk-php": "3.26.2"
以下のように送信処理を実装します。
// send.php $sqs = SqsClient::factory([ 'credentials' => [ 'key' => YOUR_KEY, 'secret' => YOUR_SECRET_KEY, ], 'region' => 'us-west-2', 'version' => '2012-11-05', ]); $time = time(); for($i =0; $i < 10; $i++){ $sqs->sendMessage([ 'QueueUrl' => 'https://sqs.us-west-2.amazonaws.com/xxx/xxxxx.fifo', 'MessageBody' => 'test body'.$i, 'MessageGroupId' => 'group', 'MessageDeduplicationId' => hash('sha256', $time.$i), ]); }
受信処理は以下のように実装します。
// recv.php $sqs = SqsClient::factory([ 'credentials' => [ 'key' => YOUR_KEY, 'secret' => YOUR_SECRET_KEY, ], 'region' => 'us-west-2', 'version' => '2012-11-05', ]); $result = $sqs->receiveMessage([ 'MaxNumberOfMessages' => 10, 'QueueUrl' => 'https://sqs.us-west-2.amazonaws.com/xxx/xxxxx.fifo', ]); foreach ($result->search('Messages[]') as $message) { $queueHandle = $message['ReceiptHandle']; $messageBody = $message['Body']; echo $messageBody."\n"; $sqs->deleteMessage([ 'QueueUrl' => 'https://sqs.us-west-2.amazonaws.com/xxx/xxxxx.fifo', 'ReceiptHandle' => $queueHandle, ]); }
実行結果
$ php send.php $ php recv.php test body0 test body1 test body2 test body3 test body4 test body5 test body6 test body7 test body8 test body9
ちなみにFIFOでない標準のキューを使用すると以下のようになります
$ php send.php $ php recv.php test body0 test body4 test body7 $ php recv.php test body5 test body8 ~略~
次に送信処理を以下のようにMessageDeduplicationIdが重複するように書き換えます
'MessageDeduplicationId' => hash('sha256', $time.$i), ↓ 'MessageDeduplicationId' => hash('sha256', $time),
実行結果は以下のように最初の1行のみキューイングされます
$ php send.php $ php recv.php test body0
但し永遠に重複idは受付しないわけではなく、300秒間のインターバルで重複メッセージを排除するようです。
FIFO (First-In-First-Out) Queues - Amazon Simple Queue Service
キューの設定に以下のように「コンテンツに基づく重複排除」の選択肢があり、これをチェックすると「sendMessage」で「MessageDeduplicationId」の指定を省略できます。
MessageBodyの内容をsha256して自動で「MessageDeduplicationId」に設定してくれるようです。
「MessageGroupId」は同じグループでの順序性を保証するための値なので適当な文字列を設定するとよさげでした。