AWS Lambda のアップデートが来た!今こそ AWS Step Functions を活用しよう

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、田中孝明です。

このエントリは、Qiitaの Serverless Advent Calendar 2017 の10日目の記事です。

re:Invent 2017で AWS Lambda で利用できる動的メモリサイズが 3GB になったことが発表されました。

【速報】AWS Lambdaで使用できる最大メモリサイズが3GBになりました #reinvent

今までデータのパース処理など、インメモリを大量に確保する必要のあるプログラムをAWS Lambda に置き換える場合、1.5GBという制約がネックになって、置き換えることが難しかったバッチプログラムもありました。
最大メモリサイズが3GBになったことで、インメモリを大量に確保するデータのパース処理も行いやすくなりました。
今こそ、 AWS Step Functions を利用したバッチプログラムを採用してみてはいかがでしょうか?

AWS Step Functions

AWS Step Functions により、視覚的なワークフローを使用して、分散アプリケーションとマイクロサービスのコンポーネントを簡単に調整できます。それぞれ別個の機能を実行する個々のコンポーネントからアプリケーションを構築することで、簡単にアプリケーションをスケールおよび変更できるようになります。

AWS Step Functions より抜粋

「CSVを取得するLambda 関数」、「CSVをパースするLambda 関数」、「エラーを通知するLambda 関数」など、Lambda 関数を用途別に分離し、 Amazon ステートメント言語 で記述することで、各Lambda 関数のワークフローを視覚的に構築することができます。

AWS Step Functionsの構築

Amazon ステートメント言語 に従ってLambda 関数を Step Functions に構築します。

あらかじめ Lambda 関数 を作成しておき、 StatesTypeTask にし、 Resource で Lambda 関数 の arn を指定します。

{
  "Comment": "An example of the Amazon States Language using a choice state.",
  "StartAt": "FetchCSV",
  "States": {
    "FetchCSV": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:fetch_csv",
      "End": "true"
    }
  }
}

すると、ワークフローに反映されます。

Lambda 関数 同士を接続する場合は、 States に新たな Task を追加し、 Next で追加した Task を記述するだけで可能となります。

{
  "Comment": "An example of the Amazon States Language using a choice state.",
  "StartAt": "FetchCSV",
  "States": {
    "FetchCSV": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:fetch_csv",
      "Next": "ParseData"
    }, 
    "ParseData": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:parse_data",
      "End": "true"
    }
  }
}

Task に関しては、タイムアウト等の設定をすることも可能です。

より複雑な行程の構築

Step Functions で利用できる ステートメント言語 には、Choiceエラー処理 もあります。
利用することで、より複雑なフローを構築することができます。

上記のような、一つの Lambda 関数 で行うとコードが煩雑になるものも、目的別の Lambda 関数 と選択処理、エラーハンドリングを組み合わせることで、視覚化できます。
ワークフローで可視化することで、複雑なフローのバッチ処理もメンテしやすくなるのではないでしょうか。

{
  "Comment": "An example of the Amazon States Language using a choice state.",
  "StartAt": "FetchCSV",
  "States": {
    "FetchCSV": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:fetch_csv",
      "Catch": [ 
        {
          "ErrorEquals": ["NotFuound"],
          "Next": "NotFuoundFallback"
        }, {
          "ErrorEquals": ["FileError"],
          "Next": "FileErrorFallback"
        } ],
      "Next": "ParseData"
    },
    "NotFuoundFallback": {
      "Type": "Pass",
      "Result": "CSV Not Fuound",
      "End": true
    },
    "FileErrorFallback": {
      "Type": "Pass",
      "Result": "File Error",
      "End": true
    },
    "CSVParseErrorFallback": {
      "Type": "Pass",
      "Result": "CSV Parse Error",
      "Next": "SendMail"
    },
    "ParseData": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:parse_data",
      "Catch": [ 
        {
          "ErrorEquals": ["CSVParseError"],
          "Next": "CSVParseErrorFallback"
        }
      ],
      "Next": "ChoiceState"
    },
    "ChoiceState": {
      "Type" : "Choice",
      "Choices": [
        {
          "Variable": "$.foo",
          "NumericEquals": 1,
          "Next": "AddOnlyFiles"
        },
        {
          "Variable": "$.foo",
          "NumericEquals": 2,
          "Next": "DeleteOnlyFiles"
        }
      ],
      "Default": "UpdateFiles"
    },
    "UpdateFiles": {
      "Type" : "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:update_files",
      "Next": "SendMail"
    },
    "AddOnlyFiles": {
      "Type" : "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:add_only_files",
      "Next": "SendMail"
    },
    "DeleteOnlyFiles": {
      "Type" : "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:delete_only_files",
      "Next": "SendMail"
    },
    "SendMail": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:send_mail",
      "End": true
    }
  }
}

まとめ

弊社もバッチシステムをStep Functionsで構築しているところがあります。
AWS Lambda の最大メモリサイズが増えたことで、大量のインメモリを必要としていたパース処理も置き換えることが可能になったのではないでしょうか?

参照