# Serverless architecture サーバーレスアーキテクチャ (Serverless architecture) あるいは サーバーレスコンピューティング (Serverless computing) とは,従来とは全く異なるアプローチに基づくクラウドシステムの設計方法である. 歴史的には, AWS が 2014 年に発表した [Lamba](https://aws.amazon.com/lambda/) がサーバーレスアーキテクチャの先駆けとされている. その後, Google や Microsoft などのクラウドプラットフォームも同様の機能の提供を開始している. サーバーレスアーキテクチャの利点は,スケーラブルなクラウドシステムを安価かつ簡易に作成できる点であり,近年いたるところで導入が進んでいる. Serverless とは,文字どおりの意味としてはサーバーなしで計算をするということになるが,それは一体どういう意味だろうか? サーバーレスについて説明するためには,まずは従来的な, "serverful" とよばれるようなシステムについて解説しなければならない. ## Serverful クラウド (従来型) 従来的なクラウドシステムのスケッチを [figure_title](#serverful) に示す. クライアントから送信されたリクエストは,最初に API サーバーに送られる. API サーバーでは,リクエストの内容に応じてタスクが実行される. タスクには,API サーバーだけで完結できるものもあるが,多くの場合,データベースの読み書きが必要である. データベースには,データベース専用の独立したサーバーマシンが用いられることが一般的である. また,画像や動画などの容量の大きいデータは,また別のストレージサーバーに保存されることが多い. これらの API サーバー,データベースサーバー,ストレージサーバーはそれぞれ独立したサーバーマシンであり, AWS の言葉では EC2 による仮想インスタンスを想定してもらったらよい. 多くのウェブサービスでは,多数のクライアントからのリクエストを処理するため,複数のサーバーマシンがクラウド内で起動し,負荷を分散するような設計がなされている. クライアントから来たリクエストを計算容量に余裕のあるサーバーに振り分けるような操作を **Load balancing** とよび,そのような操作を担当するマシンのことを **Load balancer** という. 計算負荷を分散する目的で多数のインスタンスを起動するのはよいのだが,計算負荷が小さすぎてアイドリング状態にあるようではコストと電力の無駄遣いである. したがって,すべてのサーバーが常に目標とする計算負荷を維持するよう,計算の負荷に応じてクラスター内の仮想サーバーの数を動的に増減させるような仕組みが必要である. そのような仕組みを**クラスターのスケーリング**とよび,負荷の増大に応答して新しい仮想インスタンスをクラスターに追加する操作を **scale-out**,負荷の減少に応答してインスタンスをシャットダウンする操作を **scale-in** とよぶ. クラスターのスケーリングは, API サーバーではもちろんのこと,データベースサーバー・ストレージサーバーでも必要になる. ストレージサーバーでは,例えば頻繁にアクセスされるデータはキャッシュ領域に保存したり,データのコピーを複数作るなどのスケーリングが行われる. データベースサーバーも同様に,頻繁にアクセスされるデータのアクセスがパンクしてしまわないよう,分散的な処理が必要となる. このように,**クラウドシステム内すべての箇所で,負荷が均一になるような調整が必要であり,開発者は多くの時間をそのチューニングに費やさなければならない.** また,サービスの利用者の数などに応じてスケーリングの設定は常に見直される必要があり,継続的な開発が要求される. さらに問題を複雑にするのは,API サーバーで処理されるべきタスクが,非一様な点である. 非一様であるとは,たとえばタスク A は 3000 ミリ秒の実行時間と 512MB のメモリーを消費し,別のタスク B は 1000 ミリ秒の実行時間と 128MB のメモリーを消費する,というような状況を指している. 一つのサーバーマシンが計算負荷が異なる複数のタスクを処理する場合,クラスターのスケーリングはより複雑になる. この状況をシンプルにするために,1サーバーで実行するタスクは1種類に限る,という設計も可能であるが,そうするとで生まれる弊害も多い (ほとんど使われないタスクに対してもサーバー一台をまるまる割り当てなければならない = ほとんどアイドリング状態になってしまう,など).  ## Serverless クラウドへ [Serverful クラウド (従来型)](#chap_serverful_cloud) で議論したように,クラスターのスケーリングはクラウドシステムの経済的効率とシステムの安定性を最大化するために必須の作業である. それを反映して,多くの開発者の時間が投資されてきた. クラスターのスケーリングはすべての開発者が何度も繰り返し行ってきた作業であり,いくつかの側面をテンプレート化し,共通化することができたならば開発のコストを大幅に削減できるだろう. それを実現するには,根本的なレベルからクラウドシステムの設計を考え直す必要がある. **スケーリングを前提**として考えることで,もっと**シンプルで見通しがよいクラウドシステムの設計の仕組みはないだろうか**? そのような動機が,サーバーレスアーキテクチャが誕生する背後にあった. 従来の serverful なシステムでの最大の問題点は,**サーバーをまるまる占有してしまう**という点にある. すなわち, EC2 インスタンスを起動したとき,そのインスタンスは起動したユーザーだけが使えるものであり,**計算のリソース (CPU や RAM) が独占的に割り当てられた状態**になる. 固定した計算資源の割り当てがされてしまっているので,**インスタンスの計算負荷が 0%であろうが 100%であろうが,均一の使用料金が起動時間に比例**して発生する. サーバーレスアーキテクチャは,このような **独占的に割り当てられた計算リソースというものを完全に廃止する**ことを出発点とする. サーバーレスアーキテクチャでは,計算のリソースは,クラウドプロバイダーがすべて管理する. クライアントは,仮想インスタンスを一台まるごと借りるのではなく,計算のタスクの需要が生まれる毎に,**実行したいプログラム・コマンドをクラウドに提出する**. クラウドプロバイダーは,自身のもつ巨大な計算リソースから空きを探し,提出されたプログラムを実行し,実行結果をクライアントに返す. 言い換えると,計算リソースのスケーリングやアロケーションなどはクラウドプロバイダーが一手に引き受け,ユーザーはジョブをサブミットすることに注力する,という枠組みである. これを図示すると, [figure_title](#serverless) のようになる.  サーバーレスクラウドでは,スケーリングはすべてクラウドプロバイダーが引き受けるので,スケーラビリティーが保証されている. クライアントが同時に大量のタスクを送信した場合でも,クラウドプロバイダー側の独自の仕組みによってすべてのタスクが遅延なく実行される. また,サーバーレスクラウドを利用することで,**クラウドのコストは実際に使用した計算の総量 (稼働時間) で決定される**ことになる. これは,計算の実行総量に関わらずインスタンスの起動時間で料金が決定されていた従来のシステムと比べて大きな違いである. サーバーレスクラウドは,従来のクラウドとは根本から異なったアプローチなので,コードの書き方やシステムの設計が大きく異なる. サーバーレスクラウドを開発・運用するには,サーバーレス固有の概念や用語に精通している必要がある. 以降では,実際にクラウドを動かしながら,サーバーレスをより具体的に体験していこう. 従来型の(仮想インスタンスをたくさん起動するような)クラウドシステムは,**賃貸**と似ているかもしれない. 部屋を借りるというのは,その部屋でどれだけの時間を過ごそうが,月々の家賃は一定である. 同様に,仮想サーバーも,それがどれほどの計算を行っているかに関わらず,一定の料金が時間ごとに発生する. 一方で,サーバーレスクラウドは,**電気・水道・ガス料金** と似ている. こちらは,実際に使用した量に比例して料金が決定されている. サーバーレスクラウドも,実際に計算を行った総時間で料金が決まる仕組みになっている. ## サーバーレスクラウドを構成するコンポーネント サーバーレスアーキテクチャの概要がわかってきたところで,ここでは AWS においてサーバーレスクラウドを構成する様々なコンポーネントを紹介していこう. 特に, **Lambda**, **S3**, **DynamoDB** を取り上げ,解説する ([figure_title](#fig:serverless_logos)). サーバーレスクラウドは,これらのコンポーネントを統合することで一つのシステムが出来上がる. ここでは, Lambda,S3,DynamoDB を利用する際に押さえておかなければならない知識を一通り説明しきる都合上,具体的なイメージがわきにくいかもしれない. が,続く [???](#sec_intro_serverless) でそれぞれについてハンズオン形式で演習を行うので,そこでさらに理解を深めれば大丈夫である.  ### Lambda AWS でサーバーレスコンピューティングの中心を担うのが, [Lambda](https://aws.amazon.com/lambda/) である. Lambda の使い方を [figure_title](#lambda_workflow) に図示している. Lambda の仕組みはシンプルで,まずユーザーは実行したいプログラムのコードを事前に登録しておく. プログラムは, Python, Node.js, Ruby などの主要な言語がサポートされている. Lambda に登録されたひとつひとつのプログラムを関数 (Function) とよぶ. そして,関数を実行したいときに,invoke コマンドを Lambda に送信する. Lambda では, invoke のリクエストを受け取るとただちに (数ミリセカンドから数百ミリセカンド程度の時間で) プログラムの実行を開始する. そして,実行結果をクライアントやその他の計算機に返す.  このように,Lambda では占有された仮想インスタンスは存在せず,実行を待っているプログラムだけがある状態である. invoke のリクエストに応じて,プログラムが AWS の巨大な計算機プールのどこかに配置され,実行される. 同時に複数のリクエストが来た場合でも, AWS はそれらを実行するための計算リソースを割り当て,並列的に処理を行ってくれる. 原理上は,**数千から数万のリクエストが同時に来たとしても, Lambda はそれらを同時に実行することができる**. このような,占有された仮想サーバーの存在なしに,動的に関数を実行するサービスのことを総称して **FaaS (Function as a Service)** とよぶ. Lambda ではそれぞれの関数につき, 128MB から 10240MB のメモリーを使用することができる (執筆時点の仕様). また,実効的な CPU のパワーはメモリーの量に比例する形で割り当てられる. すなわち,タスクに割り当てたメモリーの量が多ければ多いほど,より多くの CPU リソースが割り当てられることになる (しかし, RAM と CPU パワーの具体的な換算表は AWS からは公開されていない). 実行時間は 100 ミリ秒の単位で記録され,実行時間に比例して料金が決定される. [table_title](#lambda_pricing) は Lambda の利用料金表である (執筆時点で `ap-north-east1` リージョンを選択した場合).
| Memory (MB) | Price per 100ms |
|---|---|
128 | $0.0000002083 |
512 | $0.0000008333 |
1024 | $0.0000016667 |
3008 | $0.0000048958 |
| 項目 | 料金 |
|---|---|
Data storage (First 50TB) | $0.023 per GB per month |
PUT, COPY, POST, LIST requests (per 1,000 requests) | $0.005 |
GET, SELECT, and all other requests (per 1,000 requests) | $0.0004 |
Data Transfer IN To Amazon S3 From Internet | $0 |
Data Transfer OUT From Amazon S3 To Internet | $0.09 per GB |
| 項目 | 料金 |
|---|---|
Write request units | $1.25 per million write request units |
Read request units | $0.25 per million read request units |
Data storage | $0.25 per GB-month |