はじめに
今回は以下の記事で紹介したDirect Triggersにて利用している非同期呼び出しについて調べてみました。
非同期呼び出しって?
名前の通り、非同期でLambdaを呼び出す機能で、呼び出し元サービスはLambdaの処理を待つことなく、次の処理などを実施することができます。
また非同期処理の場合、呼び出し元サービスが処理結果を知る方法に少し工夫が必要になってくるのですが、再試行や、エラー通知の仕組みも備わっていました。
やってみよ!
早速非同期処理や、再試行・エラー通知周りを触ってみます。
Lambdaの準備
常に成功また、失敗するような関数を用意しました。
まずは例外処理をコメントアウトし、常に成功する状態にしておきます。
def lambda_handler(event, context):
# raise Exception(f"エラー")
print("処理実行")
return {
'statusCode': 200,
'body': '成功しました!'
}
非同期呼び出し方法
CLIで呼び出す時は、-invocation-type Event
を付与することで非同期処理になります。
aws lambda invoke \
--function-name async_test \
--invocation-type Event \
--cli-binary-format raw-in-base64-out \
--payload '{ "key": "value" }' response.json
呼び出すと、以下ような応答がありました。
{
"StatusCode": 202
}
このコードはおそらく、HTTPステータスコードの202 Accepted
を指しているものと思われます。
リクエストを受け取ったが、処理が完了していないことを表します。実際には、処理はまだ始まっていない可能性もあります。
CloudWatchLogsを見ると、実行ログが作成されているので、非同期処理を確認できます。
2025-01-19T05:04:15.826+09:00 処理実行
再試行
Lambdaの処理が失敗した場合、自動でリランをしてくれる機能です。
Lambdaの設定タブにある非同期呼び出し
のところに再試行回数が設定できます。
必ず処理が失敗するようにコードを変更し、非同期処理をしてみます。
def lambda_handler(event, context):
raise Exception(f"エラー")
print("処理実行")
return {
'statusCode': 200,
'body': '成功しました!'
}
結果は以下のようになりました。
回数 | 発生時間 | 時間差 |
---|---|---|
1 | 2025-01-19T05:10:19 | - |
2(再試行1回目) | 2025-01-19T05:11:13 | 54秒 |
3(再試行2回目) | 2025-01-19T05:13:04 | 111秒 |
公式サイトにも以下のような記載があり、概ねあっていそうです。
関数からエラーが返された場合、Lambda はデフォルトでその関数をさらに 2 回再試行します。その際、最初の 2 回の試行の間に 1 分間、2 回目と 3 回目の間に 2 分間の待機時間があります。
デッドレターキュー
デッドレターキューサービスを使用すると、非同期処理できなかったまたは、再試行を試みたが成功しなかったイベントを補足することできます。
SNSとSQSが利用できるみたいですが、今回はSNSでメールを飛ばしてみます。
2回の再試行が終わった後にメールが届きました。
シンプルな内容で、Lambda関数起動時に指定するペイロードのみです。
複数のLambda関数で利用する場合は、SNSトピックを分けた方が良いかもです。
イベント最大有効時間
未処理の非同期処理をキューで保持する時間を設定する項目です。
Lambda関数は2分待機するようにし、同時に2回非同期処理を実施してみます。
import time
def lambda_handler(event, context):
# 2分間待機 (120秒)
time.sleep(120)
print("処理実行")
return {
'statusCode': 200,
'body': '成功しました!'
}
が、エラーになりませんでした。非同期処理も並列処理で実施してくれてそうです。
次に同時実行回数を1にして実施してみます。
この状態で2回非同期処理を実施すると、1つは処理開始、1つはエラーメールが届きました。(メール内容は先ほどと同じ)
同時実行の上限数を超えた非同期処理はキューイングされた状態で待機し、そのキュー内の保持期間を超えた場合は、破棄されることがわかりました。
まとめ
Lambdaを使った非同期処理はSNS->SQS->lambdaみたいなファンアウト構成をいつも使っていましたが、直接Lambdaを非同期処理で起動するのも良いかもですね!