Help us understand the problem. What is going on with this article?

サーバーレスアプリケーションでエラーに対処する (AWS Step Functions + AWS Lambda)

More than 1 year has passed since last update.

Lambda 関数は、以下のような場合、処理に失敗することがあります。
・処理されない例外
・タイムアウトよりも長い時間実行された場合
・メモリ不足が発生した場合
このような場合、AWS Step Functions を使用して、エラーを適切に処理するサーバーレスワークフローを設計し、実行します。


1.API に模擬コールを行う Lambda 関数を作成する

この Lambda 関数では、イベントパラメータで入力として指定されたエラーコードに応じて例外を発生させ、架空の API からの応答をシミュレートします。

Lambdaを開き、「一から作成」で、Lambda 関数を以下のように設定し、「関数の作成」をクリック。
・名前:「適当な名前」
・ランタイム:「Python 3.6」
・ロール:「lambda_basic_execution」
image.png

[関数コード]を以下のように編集し、「保存」してください。
ここでは、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ロールを紐づけます。
image.png

4.エラー処理ワークフローをテストする

「実行の開始」をする。
image.png

「新しい実行」 画面でユーザーが API の部分を担当し、模擬 API によって返してもらいたいエラーコードを指定します。
以下のコードを入力し、「実行の開始」をクリックします。

{
    "statuscode": "200"
}

「入力」 をクリックし、↑ が入力されていることを確認します。
「出力」 をクリックすると、ステータスコード 200 がワークフローによって API コールの成功として解釈されたことを確認できます。
image.png

[ビジュアルワークフロー] で、各実行の実行パスを確認できます。
"Call API" をクリックすると [入力] フィールドと [出力] フィールドが展開されます。
この状態によって、指定した入力を使用して模擬 API Lambda 関数が正常に呼び出され、その Lambda 関数の出力 "200 OK" が取得されたことを確認できます。
image.png

"OK" をクリックします。
[ステップの詳細] で、前のステップの出力 (Call API) が、このステップへの入力として渡されたことを確認できます。
image.png

5.ステートマシンの実行を検証する

今回は以下の入力を指定して 「実行の開始」 をクリック。

{
    "statuscode": "503"
}

この実行は失敗すると想定しているため、驚かないでください。 以下のプロセスが実行されたことがわかります。
image.png

429 例外のシミュレーションを行います。
「実行の開始」をクリックし、以下を入力します。

{
    "statuscode": "429"
}

ワークフローの再試行動作を確認していきましょう。

[実行イベント履歴] でFunctions によって MockAPILambda 関数がもう 2 回呼び出されていることを確認します。
この呼び出しは両方とも失敗しています。この時点では、ワークフローは、API が一時的に応答していないだけと考えて、Wait and Try Later 状態 (右側の画像に表示) に遷移します。
image.png

次に、Wait 状態によって強制的に応答コードが 200 に変更されるため、ワークフローは実行を正常に完了できます。
image.png

今度は、ステートマシンによって処理されないランダムな API 応答を指定してみましょう。

{
    "statuscode": "999"
}

失敗ともちろんなる。
image.png

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away