サーバーレスアーキテクチャという技術分野についての簡単な調査

## 概要

最近になって**サーバーレスアーキテクチャ**というコンセプトが登場した。とくに注目を集めているAWS Lambdaについて調べた。サーバー保有コストがかからないのはサーバーレスアーキテクチャの大きな魅力だといえる。一方この技術分野で未解決の課題として、応答時間の予測可能性、開発環境の充実、インフラストラクチャ間の互換性、特定インフラストラクチャに依存しないアプリケーションフレームワークなどが見つかった。

## リサーチクエスチョン

サーバーレスアーキテクチャ、とくにAWS LambdaでAPIサーバーを実装する手法は有効か？　BaaSとの違いは？　十分に短い応答時間を達成できるか？　デメリットは？

## サーバーレスアーキテクチャ登場の背景

### アプリケーションサーバーとの比較

2015年になってから「サーバーレスアーキテクチャ」というコンセプトを耳にするようになった。その思想をシンプルに表現すれば「**メンテナンスすべきアプリケーションサーバーがなければメンテナンスコストはかからない**」となるだろう。

サーバーレスアーキテクチャは原始的なCommon Gateway Interface (CGI)に近いシンプルなアーキテクチャだ。サーバーレスアーキテクチャ上のファンクションは、何らかのイベントをトリガーとして呼び出される。イベントごとに実行プロセスが起動し、ファンクションの終了とともにプロセスが終了する。アプリケーションサーバーが「常駐型プロセス」を実行するインフラストラクチャだとすれば、**サーバーレスアーキテクチャは「非常駐型プロセス」をイベントによってトリガーするインフラストラクチャ**だといえるだろう。

[AWS Lambda](https://aws.amazon.com/jp/lambda/)のようなクラウドインフラストラクチャ上でサーバーレスアプリケーションを構築すれば、インフラストラクチャのスケーラビリティや可用性（アベイラビリティ）はクラウド事業者の仕事になる。**開発者はインフラストラクチャに関する仕事の多くから解放される**ということだ。

AWS Lambdaが登場してきた背景として、(1)すでにAWS上で各種データベースをはじめとする様々なクラウド部品が提供されており、Lambdaはそれらをつなぐシンプルなハブとして設計されればよかったということと、(2)すでにParse.comやFirebaseなどのBaaSが普及しており、そういったクラウドサービスへのニーズが明らかであったということの2点が上げられるだろう。

### バックエンドサービス(BaaS)との比較

サーバーレスアーキテクチャのプログラミングモデルは[Firebase](https://www.firebase.com/)や[Parse.com](https://parse.com/)のようなバックエンドサービス(BaaS: Backend as a Service)でのサーバーサイドプログラミングに近いものになる。BaaSが基本的には「データベース」であるという意味においては昔ながらの[リレーショナルデータベース上のストアドファンクション](http://www.atmarkit.co.jp/ait/articles/0209/28/news001.html)に近いプログラミングモデルだともいえる。

BaaS上のプログラミングは手軽だが制約も多い。複雑なアプリケーションを開発するというよりはデータベースの基本機能に簡単な機能拡張をほどこす程度の使い方が主流だろう。そもそもビジネスとしてのBaaSのバリュープロポジションは「手軽さ」であるし、その実現のためにデベロッパーに対して「よく考えられた制約」を課しているのがBaaSのアーキテクチャだ。BaaSの価値は設計の不自由さ（制約）と不可分なのだ。[^articulation]

[^articulation]: もしデベロッパーに多くの自由を与えるようにBaaSが発展していくとしたら、それはAWS Lambdaと大差ないアーキテクチャになっていくだろうし、そのとき「BaaS」と「サーバーレスアーキテクチャ」の区別は霧消していくだろうが、現状ではこの区別が明確であるという認識にもとづいて議論を続ける。

### サーバーレスアーキテクチャという新たな選択肢

| アーキテクチャ | 手軽さ | 自由度 | 類似モデル |
| --------------------  | -------- | ---------- | ---------------- |
| アプリケーションサーバー | 手軽ではない(low) | 自由度は高い(high) | デーモンプロセス |
| BaaS | 手軽(high) | 自由度は低い(low) | DBストアドファンクション |
| サーバーレスアーキテクチャ | そこそこ手軽(mid) | そこそこ自由(mid) | CGI/PHP |

BaaSの制約で実現しにくい要件があったときに、サーバーレスアーキテクチャという選択肢は魅力的に見えてくる。そこで今回は最も柔軟性が高いサーバーレスインフラストラクチャだと思われるAWS Lambdaを取り上げ、BaaSの代わりになりうるか検討する。

[AWS LambdaのファンクションはJava 8で書ける](http://docs.aws.amazon.com/lambda/latest/dg/java-lambda.html)。ということは[Groovy](http://www.groovy-lang.org/)でも書ける。ドメインクラスをJava/Groovyで書いてLambdaファンクションのなかで利用することができれば、サーバーレスアーキテクチャでも本格的なアプリケーションを開発できそうだ。

今後のアプリケーションインフラストラクチャ選択において、従来型のアプリケーションサーバーと、近年普及してきたBaaSに加え、サーバーレスインフラストラクチャという選択肢も増えるとすれば有意義だ。

### 非常駐型のデメリット

歴史的にはCGI/PHPのようなイベント駆動型のアプリケーション実行アーキテクチャから、プロセス常駐型のアプリケーションサーバーのアーキテクチャへと移行してきた。その論理を確認しておきたい。

アプリケーションのプロセスを起動するコストは高い。複雑なアプリケーションでは読み込むべきクラス数も膨大になる。イベント処理自体にかかる実行時間よりも、プロセスを起動するためのオーバーヘッドが大きくなる。そこでFastCGIのような手法も生み出されたが、アプリケーションの大規模化に伴って限界が訪れた。

そこでアプリケーション起動のオーバーヘッドを省くために、いちど立ち上げたプロセスを使い回してたくさんのリクエストを処理させる方式、つまりアプリケーションプロセス常駐型のアプリケーションサーバーというアーキテクチャが用いられるようになった。なおプロセス常駐型のアプリケーションをUNIXでは[デーモン](http://e-words.jp/w/%E3%83%87%E3%83%BC%E3%83%A2%E3%83%B3.html)という。

このような歴史を踏まえれば、「非常駐型であるサーバーレスアーキテクチャで十分な応答速度を出せるのか？」という疑問は避けられない。

## 調査と考察

AWS Lambdaを使ってサーバーレスアーキテクチャのアプリケーションを構築するアプローチについて調査した。S3をRESTオブジェクトサーバーとして拡張するアプローチは有望であると考えたが、現状では実現できないことが分かった。現在利用出るのはAPI Gateway経由でLambdaファンクションを呼び出すアプローチであり、まだ大規模な採用事例はないようだが、小規模なスタディのレポートならいくつも見つかった。

### S3をRESTオブジェクトサーバーとして拡張するアプローチ

Amazon S3はHTTPおよびHTTPSのGET、POST、PUT、DELETEメソッドが実装されたストレージサーバーだ。これを「RESTオブジェクトサーバー」と見なすこともできる。**JSONデータを出し入れするだけなら、Amazon S3単体でも「APIサーバー」としての要件を満たす**。とはいえ現実のアプリケーションではユーザー認証、パーミッション検査、入力値検査といった前処理(preprocess)が必要になる。ではそれらの前処理をLambdaファンクションで実現できるだろうか。

公式ドキュメントによればS3からLambdaファンクションを呼び出す設定は、S3バケットの「イベント通知」として設定される。[S3がサポートしているイベントタイプのリスト](http://docs.aws.amazon.com/AmazonS3/latest/dev/NotificationHowTo.html#notification-how-to-event-types-and-destinations)を見ると、いずれも「オブジェクトが作成された」などの過去形になっている。つまり後処理(postprocess)用のイベントしか実装できないということだ。

残念ながら現状では「S3へのJSONデータのPOSTを横取りして前処理する」といったプログラミングはできない。しかし今後の仕様変更によってLambdaでS3イベントの前処理ができるようになれば、このアプローチを再評価できるようになるかもしれない。[^postprocess-only]

[^postprocess-only]: 現状でも前処理がいらない要件ならばデータ更新機能も実現できるといえる。しかしデータ更新リクエストの結果ステータスを受け取ることすらできないUDP的なプロトコルなので、あまり現実的ではないだろう。

### API Gateway経由でLambdaファンクションを呼び出すアプローチ

Lambdaファクションを呼び出す方法としては、イベントソースから呼び出す以外に、HTTPSで直接呼び出す方法もある[^lambda-https]。Amazon API Gatewayを使ってHTTPSのメソッドとLambdaファンクションを対応づければよい[^lambda-api-gateway]。軽量なウェブアプリケーションフレームワークでHTTP(S)メソッドとコントローラーメソッドを対応づけるプログラミングモデルに似ている。サーバーレスアプリケーションをAWS Lambda上に構築するなら、当面このアプローチしかない。

[^lambda-https]: > In addition to invoking Lambda functions using event sources or through custom clients that are built using the AWS SDKs, you can also invoke your Lambda function over HTTPS. You can do this by defining a custom REST API and endpoint using Amazon API Gateway. You map individual API methods, such as GET and PUT, to specific Lambda functions. When you send an HTTPS request to the API endpoint, the Amazon API Gateway service invokes the corresponding Lambda function. --- [Core Components: Lambda Function and Event Source - AWS Lambda](http://docs.aws.amazon.com/lambda/latest/dg/intro-core-components.html)

[^lambda-api-gateway]: > AWS Lambda provides an easy way to build back ends without managing servers. --- [Walkthrough: API Gateway and Lambda Functions - Amazon API Gateway](http://docs.aws.amazon.com/apigateway/latest/developerguide/getting-started.html)

### アプリケーションフレームワーク

API Gateway経由でLambdaファンクションを呼び出すアプローチでアプリケーションを構築するためのフレームワークとして[JAWS](https://github.com/jaws-framework/JAWS)や[Fluct](https://github.com/r7kamura/fluct)があり、それに準ずるものとして[Gradle AWS Plugin](https://github.com/classmethod-aws/gradle-aws-plugin)がある。これらはAWS Lambdaに特化したフレームワークだ。

現状ではAWS Lambda以外の選択肢が事実上存在しないので、アプリケーションフレームワークがAWSに特化・依存しているのは当然とも言える。しかし今後AWS Lambdaのようなサービスがほかのクラウド事業者からも提供されるようになれば、特定クラウドインフラストラクチャに依存しないアプリケーションフレームワークが求められるようになってくるだろう。

### サーバーレスアーキテクチャのインフラストラクチャの互換性

サーバーレスアーキテクチャのためのクラウドサービスが複数のパブリッククラウドで提供されるようになれば、パブリッククラウド間およびプライベートクラウドへの移設（マイグレーション）しやすさも求められるようになってくるだろう。

簡単に予想しておくと、Dockerがアプリケーションコンテナを標準化しているように、サーバーレスファンクションの標準化が行われるようになるかもしれない。AWS LambdaがNode.jsを採用していることから、npmやpackage.jsonのような既存技術にもとづいた標準化になりそうだ。JavaScript以外の言語でも、その言語で標準的なパッケージマネジメント基盤を援用することになるだろう。

### パフォーマンス

まだサーバーレスアーキテクチャについての知見は少ないので、採用する際にはパフォーマンステストが必須だろう。利用できるデータがほかに見当たらなかったので、ここではtaka4sato氏[^taka4sato]の短いコメントを参照しておく。それによればAPI Gateway経由のLambdaファンクションの応答時間は「早いと250 msec、遅いと8000 msecぐらい」だそうだ。

とくに工夫しなくても高速なレスポンスが得られるのであれば結構だが、現時点ではそういう安易な期待は裏切られる可能性もある。パフォーマンステストや高速化設計は必要だろう。

高速化技法については第一にAmazon API Gatewayのキャッシュ機能の利用を検討したい。それによって参照系リクエスト（GET）の高速化は容易に実現できそうだ。更新系リクエストについてはケースバイケースとしか言えないが、ユーザーインタフェイスの非同期化によって解決できるケースは少なくないだろう[^async-ui]。

[^async-ui]: 一般的にデータ更新リクエストは「一瞬」で終わらず、体感時間を伴う。したがってその間「お待ちください」とするよりは、「更新中」「レスポンス待ち」であることを示しつつもユーザーに操作を継続させるような（いわゆる「モードレス」な）設計が好ましい。ユーザーにとっては「時間がかかる操作である」と分かっていれば数秒ほど待たされてもストレスに感じないということは多い。その数秒間の待ち時間にあらためて送信内容に誤りがなかったか確認するとか、ほかの画面を見るといった「有意義な」操作ができるのであれば。

[^taka4sato]: [AWS LambdaをREST API Serverっぽく使ってみる - Qiita](http://qiita.com/taka4sato/items/3a3875e839403501d835)

### エコシステムの展望

Amazon API Gatewayの発表からまだ2〜3ヶ月しか経っていないにもかかわらず、すでにJAWS、Fluct、Gradle AWS Pluginなどが提供されている。サーバーレスアーキテクチャという技術分野ではこれからさらに数多くのオープンソースプロジェクトやコミュニティが立ち上がり、デベロッパー向けのサービスも提供されるなどしてエコシステムが成長していくだろう。

Lambda+API Gatewayのエコシステム、より広義にはサーバーレスアーキテクチャのエコシステムというものが今後どれだけ成長していくかはまだ不透明だ。一時のハイプ（誇大宣伝）で終わる可能性もある[^hype-evaluation]。現時点でこの分野にコミットするのはハイリスクだといえる。

[^hype-evaluation]: たとえばクラウド上の仮想サーバーインスタンスやアプリケーションコンテナのオートスケーリング技術が飛躍的に進歩すれば、サーバーの課金単位が「インスタンスの稼働時間」から「インスタンスの実計算量」に変わるかもしれない。そうなればサーバーレスアーキテクチャのコストメリットは減じる。しかしそれでも「メンテナンスすべきサーバーがなければメンテナンスコストはかからない」というメリットは残るだろう。こう考えればサーバーレスアーキテクチャが完全なハイプとして消え去る可能性は低そうだ。

いまリスクをとってサーバーレスアーキテクチャにコミットすべきだろうか。そこでリスクに見合うだけのリターンを得られるのは、サーバーレスアーキテクチャの知識をビジネスの競争力に転換できるITベンダーだ。たとえばクラウド管理ツールのベンダーや、クラウドインフラストラクチャ管理事業者(MSP)などが該当する。いわば「サーバーレスアーキテクチャを使ってソフトウェアを開発する企業群」ではなく、「サーバーレスアーキテクチャ自体を開発・販売する企業群」こそが早期にリスクをとってコミットするだろう。

筆者の見解としてはサーバーレスアーキテクチャを「作る側」ならリスクをとってコミットしてもよいが、「使う側」ならこの技術分野に投資するのは時期尚早だと考える。「使う側」の企業は早くとも2016年春頃まで待ってみたほうがよいのではないだろうか。

## 今後の課題

今回の調査を通じてサーバーレスアーキテクチャという技術分野の課題がいくつか見えてきた：

- 応答時間の予測可能性と高速化
- 開発環境の整備、デプロイ作業の自動化
- 特定インフラストラクチャに依存しないアプリケーションフレームワーク
- インフラストラクチャ間の互換性、移設（マイグレーション）のしやすさ

## 参考資料

- [AWS Lambda (コードの実行、リソース自動管理プラットフォーム) | アマゾン ウェブ サービス（AWS 日本語）](https://aws.amazon.com/jp/lambda/)
- [AWS Lambda Documentation](http://aws.amazon.com/jp/documentation/lambda/)
- [How to build a microservice with AWS Lambda in Groovy — Medium](https://medium.com/@benorama/how-to-build-a-microservice-with-aws-lambda-in-groovy-4f7384c3b804)
- [Amazon API Gateway – API作成から動作確認までやってみる ｜ Developers.IO](http://dev.classmethod.jp/cloud/aws/api-gateway/)
- [Amazon API Gateway をクロスオリジンで呼び出す (CORS) ｜ Developers.IO](http://dev.classmethod.jp/cloud/aws/amazon-api-gateway-cors/)
- [Amazon API Gateway & Lambda & S3 で放置可能なサービスを作ってみた - Qiita](http://qiita.com/macoshita/items/10bc707a019431817952)