AWS Step FunctionsでLambda Functionでのサムネイル画像作成をシンプルに
この記事はWanoグループ Advent Calendar 2016の23日目の記事です。
Wanoグループ内でのLambda推しエンジニアとして、前回のLambda@Edgeに引き続き、2016年Re:Inventで発表された、AWS Step Functionsについての書いてみたいと思います。
##AWS Step Functionsで解決できること
なんと言っても以下の2点だと思います。
- Lambda Functionを小さい単位で維持できる
- Lambda Function間の連携にSQSやDynamoDB等を使用する必要がなくなる
Wanoでも複数のLambda Functionを活用していますが、1つのFunctionの中でいろいろなことをやりすぎたため、他のサービスにそのまま転用できなかったり、コードの見通しが悪くなったりと言ったことが出てきました。
1つ1つのFunctionを細かく分けて、SQS等を使用して連携されることも検討しましたが、リトライや分岐のためにFunctionを用意しないといけないといったことを考えると、腰が重くなっていました。
その問題点を解決してくれるのがAWS Step Functionsです。
##Lambda Functionの事例で見かけるサムネイル画像作成をStep Functionsで
Lambda Functionsの事例として、サムネイル画像を作成するサンプルをよく見かけます。
この記事でもサムネイル画像作成を例にし、以下のサムネイル画像あるあるを解決する処理をLambda FunctionとStep Functionsで実現したいと思います。
###サムネイル画像あるあるとは
- せっかくサムネイル画像で小さくしたのに、Google PageSpeedで調べたら、ロスレス圧縮したら46%小さくなるよと言われる
- 適切なContent-Typeヘッダーが付いておらずブラウザで想定外の挙動をする
- Cache-Controllヘッダーが付いておらずブラウザキャッシュが効かない
勝手にあるあると言っているだけで、私が良く忘れるだけという可能性が大きいです。。。が、今回はこれを解決することを前提として、進めたいと思います。
###Lambda Functionを実装する
Lambda Functionを小さい単位で維持することが重要なので、以下の機能で分けてLambda Functionを実装したいと思います。
- ResizeImage: 画像をリサイズするFunction
- MinifyJpeg: JPEG画像をロスレス圧縮するFunction
- MinifyPng: PNG画像をロスレス圧縮するFunction
- SetMeta: メタデータを設定するFunction
実装できたら、これらのLambda Functionを予めデプロイしておきます。
ちなみに私は以前apexを使っていましたが、最近serverless frameworkに乗り換えを進めています。
その内この辺りも記事にできたらなと。
###AWS Step Functionsを設定する
####State Machineを作る
Step Functionsの設定画面でState Machineを作ります。
設定ファイルは以下です。
- 注意
- 2016年12月23日時点で、State Machineの修正はできません。State Machineの設定ファイルもバージョン管理対象としておくことを強くおすすめします(泣きを見ました。。。)
{
"Comment": "An example of the Amazon States Language using a choice state.",
"StartAt": "ResizeImage",
"States": {
"ResizeImage": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:FUNCTION_NAME",
"Next": "JpegOrPng"
},
"JpegOrPng": {
"Type" : "Choice",
"Choices": [
{
"Variable": "$.object.fileType",
"StringEquals": "jpeg",
"Next": "MinifyJpeg"
},
{
"Variable": "$.object.fileType",
"StringEquals": "png",
"Next": "MinifyPng"
}
],
"Default": "UnsupportedImage"
},
"MinifyJpeg": {
"Type" : "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:MinifyJpeg",
"Next": "SetMeta"
},
"MinifyPng": {
"Type" : "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:MinifyPng",
"Next": "SetMeta"
},
"UnsupportedImage": {
"Type": "Fail",
"Cause": "No Matches!"
},
"SetMeta": {
"Type": "Task",
"Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:SetMeta",
"End": true
}
}
}
上記ファイルでの設定結果として以下のState Machineができます。
####State Machineを実行する
State Machineができたら、早速実行してみましょう。
Lambda Function同様コンソールからJSONを指定して実行できますので、そちらで実行します。
動きました!!
今回は、JPEG画像をイベントとして渡したので、MinifyJpegに遷移しています。
PNG画像を渡せばMinifyPngに遷移する。。。はず(もう23日が終わりそうなので、試す時間がなかったり。。。)
####State Machine実行時の注意点
注意点としては、Lambda Functionの実行ではなく、State Machineの実行という点です。
今回StartAtに指定したResizeImageが起動するイベントを実行してもState Machineは実行されず、State Machineの起動が必要になります。
残念ながら、現時点ではState Machineをイベントドリブンにすることはできないようです。
実運用では監視したいイベントを割り当てたLambda Functionを用意して、そちらからState Machineを実行するような構成にする必要があります。
####まとめ
いくつかの課題はあるものの、AWS Step Functionsを使うことで、Lambda Function間の連携がシンプルになることは間違いありません。
課題自体も恐らく時間の問題で改善されると思いますし、serverless frameworkといった周辺ツールも続々対応してくると思うので、今後も注目です!!