Lambdaの二重起動、多重起動、冪等性…で数時間ググりまくった結論です。
Lambdaが多重起動するかもしれないときっていつ?
答えは
非同期呼び出しされたときです。
同期呼び出しされたときは、一回だけ呼び出されます。
つまり、同期呼び出し時には多重起動は発生しません。
RequestResponse(同期)呼び出しオプションを使用すると、その関数は1回だけ呼び出されます。
Event(非同期)呼び出しオプションを使用する場合、関数はイベントに応答して少なくとも1回呼び出され、関数はこれを処理するためには冪等でなければなりません。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/API_Invoke.html
同期呼び出し、いいじゃん!でも失敗時リトライが必要
非同期呼び出しは失敗時にリトライしてくれます。それ故に(?)多重起動することがあるようです。
同期呼び出しは1回しか呼び出さないため、リトライ処理を自前で用意する必要があります。
そもそもなんで呼び出しに失敗するの?
ドキュメントにはこうあります。
Lambda 関数は、次のいずれかが原因で失敗する場合があります。
- 関数がエンドポイントに到達する前にタイムアウトになった。
- 関数が入力データを正しく解析できなかった。
- 関数にメモリ不足エラーまたは他タイムアウトなどのリソース制約が発生した。
失敗時はどういう挙動するの?
ドキュメントにはこうあります。
同期呼び出し – 呼び出し元アプリケーションが 429 エラーを受け取り、再試行が必要となります。
非同期呼び出し – 非同期イベントは Lambda 関数の呼び出しに使用される前にキューされます。AWS Lambda がイベントを完全に処理できない場合、呼び出しが 2 回自動的に再試行されます (再試行間には遅延があります)。
ほ〜。
Lambdaのリトライについては↑のドキュメントに詳しく書かれてそうですね。
【本題】同期呼び出しってどうやんのよ?
- コンソールで手動で呼ぶときは同期/非同期を指定することができる
- サービスがトリガーのときは、サービスごとに同期か非同期か決まっている。
つまり、
・S3がトリガー → 非同期呼び出し
・StepFunctionsがトリガー → 同期呼び出し
みたいな感じで最初から決まってるんですね。
呼び出しタイプを制御できるのは、ユーザー自身が Lambda 関数を呼び出すときのみです。
トリガーとして AWS サービスを使用する場合、呼び出しタイプはサービスごとに事前に定義されています。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-options.html
同期か非同期かわかるサービス一覧表はないの?
あるよ(声色)
こちらです。
サービスごとに同期/非同期が日本語で書いてございます。
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invoking-lambda-function.html
非同期呼び出しのときはどうやって多重起動を防げばいいの?
非同期呼び出しの場合はDynamoDBに状態書いて頑張るみたいなことが巷では書かれています。
ちょっとしたサービス作るにはつらいですね…。
おわり✨🍰✨
うーん、結局、AWS公式ドキュメントを読み込めばわかることばかりですね。
でも読むのがしんどい日本語なんだよなあ…。翻訳文だからですか…?