📝

LambdaのトリガーにSQSを指定した際のあれこれ

2023/07/17に公開

はじめに

表題の件を実施した時の知見のメモです。
設定、設定時の注意点、リトライについてなど。

作成手順

  • SQSをトリガーに設定したいlambda関数を作成
  • 作成したlambda関数のロールに「AWSLambdaSQSQueueExecutionRole」を付与する
  • 対象のlambda関数から「トリガーを追加」で設定したいSQSを選択

トリガーに設定する際の注意点

lambda関数のトリガーにSQSを設定すると、内部で自動的にSQSに対するポーリングが行われるようです(周期などの設定変更は不可能らしい)
そのため、他でもSQSを使用していてかつ無料枠に収まるつもりの回数としていても、本設定を行うことで一定回数固定で消費することになります。
「sqs 無料枠 lambda」などで検索してもらえるといくつか情報ひっかかります。

トリガー設定時の設定値について

バッチサイズ

この値を1より大きな値に設定すると、1回の実行時にlambda関数へ渡されるキューが設定した値分になります。
具体的にはlambdaに渡されるjsonが以下のようにRecordsの中身に複数のメッセージが設定された状態になります。

{
    "Records": [
        {
            "messageId": "059f36b4-87a3-44ab-83d2-661975830a7d",
            "body": "Test message.",
            "省略……": "……"
        },
        {
            "messageId": "2e1424d4-f796-459a-8184-9c92662be6da",
            "body": "Test message.",
            "省略……": "……"
        }
        ……
    ]
}

ただここで1より大きな値を設定しとき、失敗したメッセージのみ再処理やデッドレターキューに積みたい場合は、SQSの設定と戻り値を特定の形で返却する必要があります。
具体は「バッチ項目の失敗を報告」の部分に記載。

バッチウィンドウサイズ

lambdaかSQSにデータがあるかを確認するためにポーリングを実施しています(トリガーに設定すると勝手にされます)
このときにSQSのデータを収集するのにかける時間です。
まあ説明に書いてある通り以上のことはありません。

最大同時実行数

SQSに複数キューが積まれているとき、lambda関数を実行するインスタンス数をいくらにするかの設定です。
FIFOキューを指定したときは注意が必要です。
FIFOの場合は順序を維持するために、結局先頭から順に実行されることになります。
ただしメッセージグループID毎の重複排除や順序維持となるため、別々のものであればメッセージグループIDを変えておくことで複数同時実行が可能となります。

今回実施したケースだと、対象A,B,Cが存在しており、A,B,C毎に重複排除や順序維持がされていればよい状態でした。
そのため、メッセージグループID(MessageGroupId)に対象を識別するIDを設定し、メッセージ重複ID(MessageDeduplicationId)にグループ毎の固有のIDを設定することで対処していました。

バッチ項目の失敗を報告

バッチサイズで1より大きな値に設定した場合、失敗したメッセージのみ失敗を通知したい場合に必要な設定です。
本設定を有効にしたうえで、lambda関数の戻り値を以下の形式とすることで、特定のメッセージのみを失敗とさせることが可能です。
本設定を有効にしないまたは戻り値を適切なフォーマットにしていない場合は、失敗したメッセージが1つだけでも全てのメッセージが失敗となるか、全て成功扱いにしてしまう動きとなります。

{ 
  "batchItemFailures": [ 
        {
            "itemIdentifier": "失敗したメッセージId"
        },
        {
            "itemIdentifier": "失敗したメッセージId"
        }
    ]
}

参考:部分的なバッチレスポンスの実装
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/with-sqs.html#services-sqs-backoff-strategy

フィルタリング条件

イベントを処理するか否かの条件。
今回使用していないため、詳細は割愛します。

リトライについて

SQSの設定を適切にしたうえで、lambda関数から失敗を返却することで、対象のメッセージをリトライすることが可能です。
主に以下の設定値を調整する必要があります。

  • 可視性タイムアウト
  • メッセージ保持期間

キューのメッセージがlambda関数に渡されてから可視性タイムアウトで設定した時間の間は、対象のメッセージの処理が失敗していても再度lambda関数に渡されることがありません。
そして可視性タイムアウトに設定した時間が経過すると、再度lambda関数に渡されることになります。
さらにメッセージ保持期間を設定することで、メッセージが始めて処理されてから「メッセージ保持期間」が満了するまでの間、「可視性タイムアウト」毎に対象のメッセージがlambda関数に処理される動きとなります。
よって本設定で元の処理の流れにのったままリトライ処理が可能となります。

FIFOキュー使用時の注意

FIFOキューで重複排除を行うを行う場合、最大5分間の間で重複排除が行われます。
そのため、5分間の間は同一のメッセージをキューイングしても追加されません。
もしキューイング元でどうしても5分以内で同一のメッセージを送りたい場合は、重複排除IDなど別になるよう工夫が必要となります。
(そもそも同一のメッセージを5分以内に送る設計自体を考え直す方がよいかもしれませんが)

Amazon SQSメッセージ重複排除ID の使用
https://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSDeveloperGuide/using-messagededuplicationid-property.html#working-with-visibility-timeouts

その他

本記事記載時の確認用のlambda関数のサンプル
https://github.com/natsuyasai/lambda-sqs-sample

Discussion