Lambdaでのここまでの利用パターンまとめ


このクリスマスシーズンにサンタも驚きな具合で結構バズっている<a href="http://aws.amazon.com/lambda/">AWS Lambda</a>ですが、皆さん結構色々作っているので、なんかネタを追い求めるのもしんどいので、ここまでで見えてきた利用パターンやユースケースをまとめてみたいと思います。

Lambdaを誤解を恐れずに言うのであれば、クラウド上でのイベント駆動を実現するためのAWSネイティブな実行基盤です。なんかクラウドネイティブな実行基盤が駄目な方は、ぐだぐだ言わず普通にEC2でやってればよいと思います。イメージとしては下記のような形になります。今までは利用者側がポーリングして聞かなくては行けないところが、クラウド上のリソース提供の各サービスが逆に呼んでくれるところがポイントです。

![Lambdaのイメージ](https://qiita-image-store.s3.amazonaws.com/0/1234/1e808ee2-a321-0b12-acff-8e138e64e941.png "Lambdaのイメージ")


では何個かパターンをみてみましょうか。


パターン1 : データソースからメタデータを引き出して利用しやすくする
-

これがもっとも多い利用パターンだとおもいますが、S3などのデータソース側のメタデータや2次情報を人間やシステムが利用しやすいように加工するパターンです。Lambdaによってイベントモデルがpullからpushに変わることに注目して、簡単なコードは書く必要がありますが、より楽に人間やシステムの連携を行う事が出来ます。


下記の例では、DynamoDBとCloudSearchでメタデータの保存と検索の目的で利用しています。勿論片方だけでもかまわないのですが、保存を中心とするのか、検索を中心とするかで別々の責務にした方がやりやすいかなということでこの形にしています。

![S3->Lambda->DynamoDB/CloudSearch](https://qiita-image-store.s3.amazonaws.com/0/1234/6c1ff9ba-1a0d-dd4a-c39b-9fdd40fbe8e3.png "S3->Lambda->DynamoDB/CloudSearch")



パターン2 : データソースから加工情報を引き出してエンドユーザにもメリットをだす
-


また利用の別例として、ETSをからめて動画変換を実施したり、サムネイル変換することによって、エンドユーザも動画エンコードの時間短縮やサムネイル作成までの時間短縮というメリットを享受する事が出来ます。もちろんサービス提供者側も自動化というメリットを得る事が出来ます。

ETSを使うパターンはこんな感じ
![S3->Lambda->ETS](https://qiita-image-store.s3.amazonaws.com/0/1234/615ce987-a419-bec6-82c9-689adb49e9f2.png "S3->Lambda->ETS")


サムネイルを生成も同様で、出力先がS3になっただけで、パターンとしては同じになります。このようにエンドユーザもメリットを受けられる可能性があることが大事だと思いますね。


パターン3 : データソースのイベントをフックして通知する
-

次に、例えばデータソースがシステムとシステムのバウンダリや、企業間でのデータ引き渡しなどの利用を考えてみます。例えばS3を使ったデータの引き渡しなどはその最たる例で、AmazonでもIMDBとの間で掲載情報のやり取りなどを行っている例などもあるかと思います。

今までだと、S3上においたデータでのイベント発生がなかったために、ロングポーリングしてS3のバケット内のアイテムをみるか、クライアント側からの通知を信用するかしかなかったのですが（各個別の開発で書く・書かせる処理ではないという意見です）、今後はS3がイベント通知として呼び出してくれるので、こちらをフックして通知を行う事が出来ます。

例えば、SNSをフロントにして通知の詳細を隠蔽する事で、トピックにサブスクライブしている利用者（人間、システム問わず）に異なるフォーマットで同一メッセージを送信する事が出来るので、Lambdaをイベントの通知のトリガーとして使う場合には相性がとてもよいでしょう。またはChat Opsなどを実践している人は、各種コミュニケーションツールのSDKを叩いて、通知をあげるのも良いでしょう。

![S3->Lambda->SNS](https://qiita-image-store.s3.amazonaws.com/0/1234/baf5ce6a-77f7-1b1c-d139-31ef8aa15e13.png "S3->Lambda->SNS")


個人としてはLambda->SNS連携によってある程度の抽象度を保ちながら、SNSを使って通知を行う・SQS経由でアクションを工夫できる余地を残しておけるのはデザインとしてのバランスの良さがあるかなと考えています。単にSQS+SNSが好きなだけなのかもですけども。


パターン4 : データソースの保護
-

次の利用パターンとして、データソースの保護です。Lambdaによって、データソース、例えばS3の状態を取る事が出来ると考えると、その状態を見ながら、データソースを保護できる余地が生まれた、と考えます。例えば、S3へのPUT/POSTのデータ総量を計算して、過剰にデータがPUTされている場合、アクセスポリシーを変更してPUTを閉じる事が出来るので、ある特定IPからある期限で閾値を超えたらデータをあげる事が出来ないようにポリシーを変更する事も出来ます。

また、オブジェクトの内容を簡単にチェックする事も出来ます。不正なデータがあがってきていないかなどの検査を行った上で必要に応じてオブジェクトのコピーを行うことでデータの事前検査を行う事でデータ処理側の精度を高める事が出来ます。


個別の注意点としては、現在S3のLambdaの発火タイミングはS3のイベントノティフィケーションの仕組みを利用しているため、Object Creationイベントだけになっています。オブジェクトの作成、コピー、名前の変更、マルチパートアップロードに限定されていますので、削除の場合にイベント発火が出来ません。こちらは現状別の仕組みで補う必要があるでしょう（別途汚いワークアラウンドは提示します、後段で）。


![S3->Lambda and protect data source](https://qiita-image-store.s3.amazonaws.com/0/1234/d44bc40e-c793-d439-adad-5b09256ffd25.png "S3->Lambda and protect data source")


デザインのポイントとしては、
* ポリシーの反映をどこまでLambdaだけで行わせるか、その検証をどうするか？
* データの分類の場合、データをコピーする時間をどこまで許容できるか？

あたりと思います。ユースケースによってはあわないですね(async copyとかであればいいですが)。


パターン5 : データの外部への安全な公開
-

これはS3に特化したパターンになりますが、データソースにデータがあがってきたタイミングで外部公開用のURLを生成する事でいわゆる限定コンテンツ用URLなどを生成する事が出来ます。簡単なパターンですが、えてしてこういうのが割と面倒だったりするので、うまくはまるパターンだなと思います。

![Lambda and signed url](https://qiita-image-store.s3.amazonaws.com/0/1234/7fa8ce33-ee7d-4ce8-e375-7c090cd07a08.png "Lambda and signed url")


やってないですが、例えば、加えてS3 TTL設定とオリジナルをどこかにコピーしておくことで、かなり確度の高い期間限定コンテンツなども出来るかもしれませんね。


パターン6 : 検査・マニフェストの生成・ジョブフロー実行
-

現状ここまでの利用はまだまだ見えてきていませんが、Lambdaを多段で組み合わせて、簡単なものであればジョブフローを組めます（あまり難しい事はしない方が良いと思いますが）。


![Simple job flow with Lambda](https://qiita-image-store.s3.amazonaws.com/0/1234/461e30e1-6eba-8f65-8862-c6f83bb6a01f.png "Simple job flow with Lambda")



パターン1のDynamoDB/CloudSearchを実行基盤でのトレーサビリティの確保につかいます。その上で、
1. 最初のLambdaコードでデータの検査とデータソースであがってきたデータに応じてマニフェストの生成を行います。マニフェストには例えばデータの範囲、動かすべきロジックを記載します
2. このマニフェストを別のS3バケット(*1)にアップロードします
3. *1にフックしてあるLambdaファンクションはこのマニフェストに従い、ジョブフローを実行します。この例では最終ジョブ実行先をSWFにしていますが、別になんでもかまわないと思います

ポイントとしては、
* <b>データの検査とジョブフロー実施の分離</b>
* <b>マニフェストの生成とS3アップロードにより、追跡しやすい・かつリトライ可能な状況に出来る。InvokeAsyncでLambda->Lambdaでもかまわないと思いますが、堅牢で安心なS3先生がいるのですから、一旦アップロードしてマニフェストがきっちり保存される方が障害時には追跡しやすいと思います</b>
* DynamoDBとCloudSearchにより、イベントの流れが保存されており、検索可能な状況
* 最初のLambdaでごにょごにょしてFunctionを組んで、次のLambdaに渡すあたりは黒魔術ですw（まあでもみんな思いつきますよね）

のあたりかと思います。



パターン7. デプロイまわりでの利用
-

老害なので今時の若者の呼び方がわかっていませんが、アーティファクトを保存する先としてはS3は非常に優れた手段だと思います。ここでいうアーティファクトはJavaで言う所のjar/warなどや、AMIなどです。CI動かして、S3にアーティファクトアップロードしてくれるものはどこでもプラグインぽくついてくれていそうです。ここまでくれば、CI->S3->本番環境への反映までLambdaで自動化できそうです。

下記のイメージではLambda内からOpsWorksでの反映を実行できる感じをイメージしています。これはまだやっていないので書くかどうか迷いましたが、多分出来ると思うので誰かやってみてください（w）


![Lambda and OpsWorks](https://qiita-image-store.s3.amazonaws.com/0/1234/f7f676f4-10b4-1982-c127-e87af19d1225.png "Lambda and OpsWorks")



おまけ : S3の削除チェック
-

S3削除はLambdaのイベントとして（現状は受け取れないので）下記のような感じでやるしかないと思います。とはいえ、S3 DELETEはEventual Consistencyなので、チェックする側はリトライなど気にする必要があります。そのため、例えば各ユーザでのデータ総容量の計算での利用など正確性が求められる場合は、LambdaというよりEMRなどでデータ量の計算はする必要があると思います。


![Lambda and S3 DELETE](https://qiita-image-store.s3.amazonaws.com/0/1234/60175a62-f457-e2bd-924b-3932652ccab0.png "Lambda and S3 DELETE")


おまけその2 : S3上にあがったファイルをEC2上のNFSやらに反映したい
-

まあこんな使い方もあるよ、というところで。EC2上でNFSでもなんでもかまわないですが、こちらに反映したい、けどなんか毎回S3上をポーリングするのに疲れた方はいらっしゃるかと思います。そこで、こんな感じでLambdaがS3にデータがPUTされたタイミングでデータコピーしてくれたらなあ、ぽわわーんとか思ってる人も多いかと思います。

![Lambda and EC2](https://qiita-image-store.s3.amazonaws.com/0/1234/7cee3e4c-9a85-2cea-c1fd-9d8a10fda407.png "Lambda and EC2")


まあこう動いてくれればうれしいのですが。実際はファイル容量もあって、Lambda内からの直コピーは避けた方がよいというのが私の意見です。というわけで現実路線としては下記のような感じじゃないかと思われます。嬉しい誤算としては、下記のやり方だと途中にワーカーが入るので、こいつでウイルス検査・復号化などをやってあげられる余地があるのはいいんじゃないかと思います。でもこうすると、S3にお伺いたてる手間だけが減った感じになりますが、まあそこはご愛嬌で（だからおまけなわけですし）。



![Lambda and EC2 part2](https://qiita-image-store.s3.amazonaws.com/0/1234/93e6d06b-558f-6dcb-1b27-958e5f691ee9.png "Lambda and EC2 part2")



総括
-

Lambda、ユースケースとして色々出来そうな事がわかって頂ければよいかなと思います。とはいえ、個人的な感覚としては下記のような点に注意した方がよいと思います。

<b>
* StatelessがLambdaコードの基本なので、状態を持たない処理に限定する。
* KISS原則を守る。単一処理を基本として、あまり難しい事はやらない
* 複数の処理になる場合、分割してチェーンさせましょう
* チェーンさせる場合、呼び出し元・呼び出し先の間の追跡性は確保する必要はありそう
</b>

いかがでしたでしょうか？Lambda、クラウド時代の新しいプラットフォームとしてぜひ使ってみてください。


リファレンス
-

この投稿は、ここまでで見えた利用パターンというお題目で、<del>筆者のスケジュール能力の無さをいいことに</del>かなりの割合を<del>パクリ</del>参考にさせていただいてますので、さくっとリンクだけはっておき、感謝の意とさせていただければと。

<a href="http://qiita.com/shot6/items/bcb91ae9d5198fcb224c">LambdaをつかってS3にPUTされた情報のメタデータをDynamoDBで楽に管理する</a>
<a href="http://qiita.com/con_mame/items/b58a5e017e7c9ab2356b">AWS LambdaとElastic Transcoder</a>
<a href="http://qiita.com/ryo0301/items/7f9fd8024987526cbc30">S3に画像をアップロードしたらLambdaでサムネイルを生成する(node-imagemagick)</a>
<a href="http://qiita.com/aquaviter/items/ae32b24ccef491bf9e7d">AWS Lambdaを使ってS3の署名付きURLを自動的に発行する</a>
<a href="http://qiita.com/c9katayama/items/706f8198d76f2232e874">AWS Lambdaを使って、S3のデータ利用量を制限する</a>



お約束ですが、こちらは個人の意見でして、所属する会社・団体とは全く関係がありませんのでご了承ください。