この記事は公開されてから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 関数 を作成しておき、 States
の Type
を Task
にし、 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 の最大メモリサイズが増えたことで、大量のインメモリを必要としていたパース処理も置き換えることが可能になったのではないでしょうか?