サーバレスアーキテクチャの考え方
Amazon Web ServicesがAWS Lambdaを発表したのはAWS re:Invent 2014で、サーバレスアーキテクチャの考え方が初めて世に出てきた日と考えて良いでしょう。
この発表ではAmazon.comのCTOであるWerner Vogels氏自らがAWS Lambdaについて紹介を行いました。
Werner氏は、同発表にておおよそ以下のように述べています。
アプリケーションの基本的要素は以下のように捉えることができる。
イベントが発生すると、別の関数がイベントに反応し、値がアップデートされる。これはつまり、関数とデータがイベントをトリガーとして相互にインタラクションする世界だ。
上記を前提として考えると、基本的な要素というのはコンポーザブルかつ変更などが容易で、いつも値が最新に保たれるダイナミックなものだといえる。
上記の考え方はAWS Lambdaが初めて世に送り出したものではなく、Node.jsがその先駆けであると考えることができます。
Node.jsはイベント化された入出力を扱うUnix系プラットフォーム上のサーバーサイド、JavaScript環境であるとともに、シングルスレッドにおける非同期処理を容易に実装可能にしたイベント駆動型プログラミング環境です。
この考え方をさらに発展させたものがAWS Lambdaである、と捉えることもできるでしょう。
サーバレスアーキテクチャが向くもの、向かないもの
サーバレスアーキテクチャは残念ながら、現時点では全てのWebサービス・Webシステムに適用可能な銀の弾丸ではありません。
現状、サーバレスアーキテクチャが効果的だと考えられるシステムには以下のようなものが挙げられます。
- 時間帯や季節によって、サービスやシステムへのアクセス数や負荷が大幅に上がるもの
- 一つひとつの処理自体は短時間で終わるが、大量のユーザーを捌く必要のあるもの
上記の特性を持つシステムには、iPhone/AndoridアプリのAPIサーバーや、シングルページアプリケーション(SPA)で構成されているWebサービスなどが該当するでしょう。
他にも、テレビCMに連動したランディングページや、イベント会場での入場管理システムなどもサーバレスアーキテクチャが効果的だと考えられそうです。
Webシステムに求められる内容の変化
さて、5年ほど前までは、ほとんどのWebサービス・Webシステムは単体で完結しており、他のシステムとの連携を前提としないモノリシックなものがメインでした。
ところが、TwitterやFacebook、Slackなどを始めとしたOAuthやAPIを利用したマイクロサービスが台頭し、ネットワークの速度向上、そしてインターネットへの安価な常時接続が一般化したことにより、個々のサービスそのものはビジネス処理機能の単位で小さなサービスに分割されました。それらをAPIで繋ぐことで、個々のサービスをシンプルに保ちながら、モノリシックなサービスと同等な機能を持たせることが可能となってきたのです。
モノリシックなアプリケーションからマイクロサービスに移行することによる拡張性や柔軟性
モノリシックなアプリケーションにも、もちろんメリットはあります。
マイクロサービスの特徴とも言えるAPI通信は、そのほとんどがJSONもしくはXML形式でデータのやりとりをするので、どうしても送受信するデータを内部的なデータに変換して扱う必要があります。また、サーバー間の通信が発生することが前提になるので、複数のAPIサーバー間での通信のどこかでエラーが発生した時、ハンドリングなどが複雑になりがちです。
一方で、モノリシックなアプリケーションの場合は、基本的に[ロードバランサ]<->[Webサーバー]<->[アプリケーションサーバー]<->[データベースサーバー]の4つのレイヤーで構築されるため、送受信するデータの変換回数はマイクロサービスに比べて少ないです。また、アプリケーションサーバーから見た場合に、通信先が「Webサーバー」と「データベースサーバー」の2箇所に限定されるなど、各レイヤー間の通信経路がマイクロサービスに比べて明確なため、エラーが発生したときのハンドリングを比較的簡単に行うことができます。
したがって、アプリケーションの特性やビジネス要件を踏まえた上で、マイクロサービス型の開発を行うのか、モノリシック型の開発を行うのかを検討する必要があるでしょう。
サーバレスアーキテクチャの特性と欠点
サーバレスアーキテクチャは、マイクロサービス型の開発に適した、イベントドリブンなアーキテクチャです。この特性をフルに活かすためには、非同期に処理が行われることを前提にした設計を行う必要があります。
イベントドリブンなアーキテクチャとは、どのようなものでしょうか。身近な例で考えてみましょう。
私たちが音楽を聴いたり、テレビを見たりする際には、リモコンなどの音量ボタンを押して最適な音量に調整を行います。この、[音量ボタンを押す]という動作がイベントに該当します。テレビやオーディオデバイスは、[音量ボタンを押す]イベントをきっかけに[音量の変更]を行います。このイベントをきっかけに何らかの動作が行われることをイベントドリブンと呼びます。
上記の例では[音量ボタンを押す]イベントをきっかけに[音量の変更]イベントが発生しました。
さらに続きを考えていくと、[音量の変更]イベントが発生すると、スピーカーやイヤホンに対して[電圧の変更]イベントが発生します。我々はその結果、スピーカーやイヤホンから[音量の変化]というフィードバックを得ます。このフィードバックを元に、再度[音量ボタンを押す]イベントを発生させるかどうかを考えるわけです。
このように、身近な行動一つをとっても、我々は対象に対してイベントを発生させ、その結果をフィードバックとして得て生活をしています。
モノリシックなアプリケーションの場合でも、同様にクラスやメソッドを作成し、それぞれの間でイベントの発生(メソッド呼び出し)とフィードバック(戻り値)を得ることでアプリケーションは動作しています。
それでは、サーバレスアーキテクチャの場合、イベントとフィードバックの関係はどのように変化するのでしょうか。
前述の通り、サーバレスアーキテクチャでは、非同期に処理が行われることを前提に設計します。これも身近な例で考えてみましょう。
私たちが居酒屋に行くと、さまざまな飲み物や食べ物を注文します。一度にたくさんの注文を行うと、厨房では手の空いている人が1品ごとに商品を作っていきますが、注文した商品によって、できあがるまでの時間が異なります。そのため、居酒屋で注文した商品は、必ずしも注文した順番通りに来ることはなく、準備ができた商品から順に提供されることになります。
一方で、全ての商品が提供されると、伝票が渡され、私たちは提供された商品を堪能した後、追加で注文をするか、お金を払ってお店を出て行くかの選択をすることになります。
上記の居酒屋の流れは、まさに非同期的な処理と言うことができるでしょう。
[注文]というイベントは、厨房に行った時点で[商品の作成]という複数の細かいイベントに分割されます。厨房には複数の人がいて、それぞれの人が[商品を作成する]イベントを実行します。商品の作成が終わったら、随時[配膳する]というイベントが行われ、注文者である私たちのテーブルに届けられます。[注文]イベントから派生した[配膳する]イベントが全て完了すると、[伝票の発行]イベントが行われます。
ここにサーバレスアーキテクチャの利点と欠点があります。居酒屋の例を続けましょう。
居酒屋が私たちの注文した商品を一気に提供したければ、厨房で働く人を無限に増やすことで全ての商品を一斉に作ることができるのは容易に想像ができるかと思います。サーバレスアーキテクチャはFaaS型のサービスですので、この「厨房で働く人(Function)」は、FaaS側のリソースが許す限り、ほぼ無限に自動で増やすことが可能です。
一方で、厨房で働く人をどれだけ増やしたとしても、注文した商品によって、できあがるまでの時間(レスポンスタイム)はどうしても異なります。
さらに、オーダーがきちんと通っていなかったり、折角厨房で商品を作っても配膳できる人が限られている(HTTP接続数の上限)と、やはり商品の提供は遅れてしまいます。
私たちは経験的にどの商品を注文するとどの程度の時間で来るかをおおよそ理解しているため、あまりにも時間がかかる(タイムアウト)と、オーダーがきちんと通っているか確認したり、時にはもう一度オーダーをすることもあります。
このように、サーバレスアーキテクチャはFunctionの実行数をほぼ無限に増やすことが可能な一方、複雑な処理を行うとどうしてもFunction単体のレスポンスタイムは長くなります。また、非同期的な処理を行っているため、Functionに対してイベントが正しく発行できていなかったり、Functionが何かしらのエラーで止まってしまった場合などのエラーハンドリングは、モノリシックなアプリケーションに比べ、補足そのものが難しいです。そのため、例外の考慮が必要で、それが発生した時の対処の設計コストが高くなりがちです。
例外の設計が難しいことに関連して、FaaSやNoSQLを利用したサーバレスアーキテクチャでは、複数の関数にまたがるトランザクション処理を行うことがモノリシックなアプリケーションに比べて非常に難しくなっています。RDBMSでは簡単にできるトランザクション処理も、イベントベースでFunctionからFunctionへと流れ作業を行うような形で処理をしていく設計が求められてきます。
そのほか、モノリシックなアプリケーションに比べ、FaaSを提供しているベンダー側でインフラの運用管理を担保するため、インフラ管理のコストは下がる傾向にありますが、同時にモノリシックなアプリケーションに比べてベンダーロックインが強くなりがちな傾向もあります。これは、より安価で新しいFaaSサービスが出てきた際に、乗り換えを行うことが難しくなることが想定されます。
以上のとおり、モノリシックなアプリケーションとサーバレスアーキテクチャを採用したアプリケーションでは、それぞれメリット/デメリットが異なります。サーバレスアーキテクチャの採用にあたっては、その双方を理解した上で検討することを強くお勧めします。