SQSでLambdaをトリガーする際の挙動について曖昧だったので改めて調べてみました。
イベントソースマッピング
SQSでLambda関数をトリガーする場合、イベントソースマッピングというLambdaの機能が使用されます。
イベントソースマッピングは、ストリームやキューからデータを受け取りバッチで処理するLambdaの機能です。SQSでLambda関数をトリガーする際にはこの機能を経由します。他にもKinesis、DynamoDBでトリガーする際に使用されます。
- Lambda側からポーリングでデータを取得
- 複数のデータをバッチでまとめて効率的に処理
- 実行失敗時のデータに対する処理が組み込まれている(SQSならdead letter queue、DynamoDBならon-failure destination)
参考:
SQSでLambda関数をトリガーする際の挙動
- LambdaはSQSをポーリングして、バッチとして同時に複数件のメッセージを受信します
- 1バッチに対して一回のLambda関数が実行されます
- 受信されたメッセージは一時的に非表示になり、他のリソースから処理できなくなります
- 処理が成功した場合、メッセージは削除されます
sequenceDiagram
participant SQS
participant ESM as Event Source Mapping
participant Lambda function
ESM->>SQS: Poll Messages
SQS-->>ESM: Return Messages
Note over SQS: 受信されたメッセージを<br>一時的に非表示にする
ESM->>Lambda function: Invoke Function
activate Lambda function
Note over Lambda function: メッセージ処理中
Lambda function-->>ESM: Success Response
deactivate Lambda function
ESM->>SQS: Delete Message
Note over SQS: メッセージが削除される
参考:
補足:イベントソースマッピングなしで直接トリガーする場合の特徴
API Gateway、S3、AWS IoTなどから直接Lambda関数をトリガーした場合の特徴:
- 1イベントに対して1回のLambda関数の実行
- ポーリングを待たずに、イベント発生直後に関数を実行できるのでリアルタイムな処理に向いている
- 実行失敗時のデータの処理は自前で実装する必要がある
参考:
補足:Lambda関数の同期呼び出しと非同期呼び出し
Lambda関数の呼び出しは同期呼び出しと非同期呼び出しに分類されます。
- 同期呼び出し: 呼び出し元が実行完了まで待機。エラー時は呼び出し元にエラーレスポンスが返される(API Gateway、ALB、Amazon Cognitoなど)
- 非同期呼び出し: 呼び出し元は実行完了を待たない。Lambda側でエラーが発生した場合は自動的に複数回リトライされる(S3、SNS、EventBridgeなど)
With Amazon SQS event source mappings, Lambda polls the queue and invokes your function synchronously with an event.
SQSの場合はイベントソースマッピング内で同期的にLambdaを呼び出してエラーハンドリングをしているそうです。
参考:
SQSでLambda関数をトリガーする際のエラー時の動作
Lambda関数でエラーが発生した際の動作は以下のようになります。
- Lambda関数がエラーで終了した際はメッセージは削除されずに残ります
- 可視性タイムアウトの時間が経過して再表示された際にメッセージは再度実行可能になり、再度ポーリングで取得された時にリトライされます。
sequenceDiagram
participant SQS
participant ESM as Event Source Mapping
participant Lambda function
ESM->>SQS: Poll Messages
SQS-->>ESM: Return Messages
Note over SQS: 受信されたメッセージを<br>一時的に非表示にする
ESM->>Lambda function: Invoke Function
activate Lambda function
Note over Lambda function: 処理失敗
Lambda function-->>ESM: Error Response
deactivate Lambda function
Note over SQS: 非表示になったメッセージを<br>可視性タイムアウト後に再表示
ESM->>SQS: Poll Messages
SQS-->>ESM: Return Messages
Note over SQS: 受信されたメッセージを<br>一時的に非表示にする
ESM->>Lambda function: Invoke Function
activate Lambda function
Note over Lambda function: 再度失敗
Lambda function-->>ESM: Error Response
deactivate Lambda function
Note over SQS: リトライ継続...
参考:
デッドレターキュー(DLQ)
デッドレターキューが設定されている場合、設定した回数以上リトライされたメッセージは指定されたキューに移動されます(デフォルトは10回)。
デッドレターキューの利点:
- 問題のあるメッセージが繰り返し処理されてシステムのパフォーマンスを下げることを防ぐ
- 問題のあるメッセージを分離することでデバッグや監視をしやすくする
sequenceDiagram
participant SQS
participant ESM as Event Source Mapping
participant Lambda function
participant DLQ as Dead Letter Queue
Note over SQS: 最大受信回数に達したメッセージ
ESM->>SQS: Poll Messages
SQS-->>ESM: Return Messages
Note over SQS: 受信されたメッセージを<br>一時的に非表示にする
ESM->>Lambda function: Invoke Function
activate Lambda function
Note over Lambda function: 処理失敗
Lambda function-->>ESM: Error Response
deactivate Lambda function
Note over SQS: 最大受信回数に達した
SQS->>DLQ: Send to Dead Letter Queue
Note over DLQ: メッセージがDLQに移動
参考:
おわりに
今回はSQSでLambda関数をトリガーする際の挙動について調べてました。
- SQSとLambdaの連携においてイベントソースマッピングという仕組みによって、メッセージがバッチで処理される
- 処理に失敗したメッセージは自動的にリトライされ、デッドレターキューを活用することで問題のあるメッセージを適切に処理できる仕組みになっている
これらの特徴を加味した上で設計していきたいです。