Lambda 関数は、以下のような場合、処理に失敗することがあります。
・処理されない例外
・タイムアウトよりも長い時間実行された場合
・メモリ不足が発生した場合
このような場合、AWS Step Functions を使用して、エラーを適切に処理するサーバーレスワークフローを設計し、実行します。
###1.API に模擬コールを行う Lambda 関数を作成する###
この Lambda 関数では、イベントパラメータで入力として指定されたエラーコードに応じて例外を発生させ、架空の API からの応答をシミュレートします。
Lambdaを開き、「一から作成」で、Lambda 関数を以下のように設定し、「関数の作成」をクリック。
・名前:「適当な名前」
・ランタイム:「Python 3.6」
・ロール:「lambda_basic_execution」
[関数コード]を以下のように編集し、「保存」してください。
ここでは、API の模擬応答を実行する簡単な Lambda 関数の作成です。
class TooManyRequestsException(Exception): pass
class ServerUnavailableException(Exception): pass
class UnknownException(Exception): pass
def lambda_handler(event, context):
statuscode = event["statuscode"]
if statuscode == "429":
raise TooManyRequestsException('429 Too Many Requests')
elif statuscode == "503":
raise ServerUnavailableException('503 Server Unavailable')
elif statuscode == "200":
return '200 OK'
else:
raise UnknownException('Unknown error')
画面右上の ARN を書き留めておいてください。
###2.IAM ロールを作成する###
[このロールを使用するサービス]で「Step Functions」を選択してIAM ロールを作成しておいてください。
###3.Step Functions のステートマシンを作成する###
Step Functions を開き、「一から作成」します。
[名前]:適当な名前
[ステートマシンの定義]:以下のコードを入力します。
なお、Resource 部分は自分のものにかえてください。
{
"Comment": "An example of using retry and catch to handle API responses",
"StartAt": "Call API",
"States": {
"Call API": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Next" : "OK",
"Comment": "Catch a 429 (Too many requests) API exception, and resubmit the failed request in a rate-limiting fashion.",
"Retry" : [ {
"ErrorEquals": [ "TooManyRequestsException" ],
"IntervalSeconds": 1,
"MaxAttempts": 2
} ],
"Catch": [
{
"ErrorEquals": ["TooManyRequestsException"],
"Next": "Wait and Try Later"
}, {
"ErrorEquals": ["ServerUnavailableException"],
"Next": "Server Unavailable"
}, {
"ErrorEquals": ["States.ALL"],
"Next": "Catch All"
}
]
},
"Wait and Try Later": {
"Type": "Wait",
"Seconds" : 1,
"Next" : "Change to 200"
},
"Server Unavailable": {
"Type": "Fail",
"Error":"ServerUnavailable",
"Cause": "The server is currently unable to handle the request."
},
"Catch All": {
"Type": "Fail",
"Cause": "Unknown error!",
"Error": "An error of unknown type occurred"
},
"Change to 200": {
"Type": "Pass",
"Result": {"statuscode" :"200"} ,
"Next": "Call API"
},
"OK": {
"Type": "Pass",
"Result": "The request has succeeded.",
"End": true
}
}
}
「既存のIAMロールを作成する」を選択し、2.で作成したIAMロールを紐づけます。
###4.エラー処理ワークフローをテストする###
「新しい実行」 画面でユーザーが API の部分を担当し、模擬 API によって返してもらいたいエラーコードを指定します。
以下のコードを入力し、「実行の開始」をクリックします。
{
"statuscode": "200"
}
「入力」 をクリックし、↑ が入力されていることを確認します。
「出力」 をクリックすると、ステータスコード 200 がワークフローによって API コールの成功として解釈されたことを確認できます。
[ビジュアルワークフロー] で、各実行の実行パスを確認できます。
"Call API" をクリックすると [入力] フィールドと [出力] フィールドが展開されます。
この状態によって、指定した入力を使用して模擬 API Lambda 関数が正常に呼び出され、その Lambda 関数の出力 "200 OK" が取得されたことを確認できます。
"OK" をクリックします。
[ステップの詳細] で、前のステップの出力 (Call API) が、このステップへの入力として渡されたことを確認できます。
###5.ステートマシンの実行を検証する###
今回は以下の入力を指定して 「実行の開始」 をクリック。
{
"statuscode": "503"
}
この実行は失敗すると想定しているため、驚かないでください。 以下のプロセスが実行されたことがわかります。
429 例外のシミュレーションを行います。
「実行の開始」をクリックし、以下を入力します。
{
"statuscode": "429"
}
ワークフローの再試行動作を確認していきましょう。
[実行イベント履歴] でFunctions によって MockAPILambda 関数がもう 2 回呼び出されていることを確認します。
この呼び出しは両方とも失敗しています。この時点では、ワークフローは、API が一時的に応答していないだけと考えて、Wait and Try Later 状態 (右側の画像に表示) に遷移します。
次に、Wait 状態によって強制的に応答コードが 200 に変更されるため、ワークフローは実行を正常に完了できます。
今度は、ステートマシンによって処理されないランダムな API 応答を指定してみましょう。
{
"statuscode": "999"
}