AWSでサーバレスアーキテクチャを試す
それでは実際にAWS Consoleから、LambdaとAPI Gatewayによる簡単なAPIの実装を試してみましょう。
今回実装するAPIは以下の通りです。
-
GET
リクエストに対してHello, Lambda!
の文字列を返却する -
クエリストリングに
name
が含まれている場合は、Hello, ${name}!
の文字列を返却する -
GET
以外のメソッドに対しては、405(Method Not Allowed)のHTTPステータスコードを返却する
Lambda関数の作成
AWSマネジメントコンソールから、[Lambda]をクリックします。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_01_s.png)
Lambdaの画面で、[今すぐ始める]をクリックします
もし、すでに作成したLambda関数がある場合は、[Lambda 関数の作成]をクリックします。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_02_s.png)
(1)設計図の選択
まずは設計図(blueprint)を選択します[3]。
利用する言語やシナリオを元に設計図を選択し、必要に応じてカスタマイズすることができます。
今回はランタイムに[Node.js 6.10]を選択し、その中の[hello-world]テンプレートを用います。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_03_s.png)
注
[3] 設計図とは、Lambda関数のトリガーとなるイベントソースと、そのイベントソースに対応したLambda関数のテンプレートです。設計図を用いないで独自にイベントソースやLambda関数を開発することも可能です。
(2)トリガーの設定
このテンプレートでは、トリガーとなるイベントソースがデフォルトでは設定されていません。
[API Gateway]を選択し、API Gatewayのプロキシ統合タイプをイベントソースとして設定します。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_04_s.png)
- [API名]に「lambda-first-api」と入力
- [デプロイされるステージ]はデフォルトの「prod」を選択
- [セキュリティ]は「オープン」を選択
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_05_s.png)
入力ができたら、[次へ]をクリックします。
(3)関数の設定
続いて関数の設定を行います。
ここで、API Gatewayが受け付けたリクエストに対して、どのようなレスポンスを返却するかを定義します。
[名前]に「hello-lambda」と入力します。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_06_s.png)
Lambda関数のコードの下にある、「Lambda関数ハンドラおよびロール」セクションで以下の通り設定します。
- [ロール]で「テンプレートから新しいロールを作成」を選択
- [ロール名]に「hello-lambda-role」と入力
- [ポリシーテンプレート]で「シンプルなマイクロハーネスのアクセス権限」を選択
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_07_s.png)
「Lambda関数のコード」セクションでは、Lambdaで実行されるコードを設定します。今回は「コードをインラインで編集」機能を利用して直接JavaScriptを記述していきますが、[コード エントリ タイプ] で選択できるように、.zip
ファイルでのアップロードやS3経由でのファイルアップロードも行うことが可能です。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_08_s.png)
今回利用するLambda関数のコードは以下の通りです。
'use strict'; console.log('Loading function'); exports.handler = (event, context, callback) => { let response; switch (event.httpMethod) { case 'GET': let name = 'Lambda'; if (event.queryStringParameters && event.queryStringParameters['name']) { name = event.queryStringParameters.name; } response = { statusCode: 200, body: `Hello, ${name}!` }; break; default: response = { statusCode: 405, body: 'Method Not Allowed' }; break; } callback(null, response); };
Lambda 関数で利用可能な引数は以下の通りです。
-
event
:API Gatewayから渡されるリクエストのイベントデータ -
context
:実行中のLambda関数のランタイムの情報 -
callback
:呼び出し元であるAPI Gatewayにレスポンスを返す際に使用するコールバック関数
API Gatewayのプロキシ統合タイプではstatusCode
だけでなく、必要に応じてbody
やheaders
を含むレスポンスオブジェクトを返却する必要があります。
event
に含まれるリクエストの情報に基づいて必要な処理を行った上で、レスポンスオブジェクトを組み立て、API Gatewayにcallback
を返却するという流れが基本となります。
全ての設定及びLambda関数のコードの入力が完了したら、[次へ]をクリックします。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_09_s.png)
(4)確認
設定内容を確認し、問題がなければ[関数の作成] をクリックします。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_10_s.png)
(5)実行
関数が作成されたら、実際に動かしてみましょう。
- [トリガー]タブを選択します
- エンドポイントに割り振られたURLをクリックします
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_11_s.png)
ブラウザにHello, Lambda!
と表示されます。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_12_s.png)
続いて、URLに?name=John
のクエリパラメータを追加すると、Hello,John!
とレスポンスが動的に変更されることが確認できます。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_13_s.png)
(6)API Gatewayの確認
以上でAPIの実装は完了ですが、API Gatewayの設定も少し見てみましょう。
[prod]のリンクをクリックすると、API Gatewayの設定ページに遷移します。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_14_s.png)
[lambda-first-api]の[リソース]をクリックし、[/hello-lambda]以下の[ANY]をクリックすると、API全体の流れを確認することができます。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_15_s.png)
lambda-first-api
APIのhello-lambda
リソースでANY
を定義した結果「全てのメソッドに対して統合リクエストタイプLAMBDA_PROXY
を経由してLambda関数hello-lambda
を呼び出す」という設定が行われています。
これにより、API Gatewayによって適切なLambda関数が呼ばれ、関数内のソースコードが実行された結果をHTTPレスポンスとしてクライアントへ返却することが可能になっています。
[統合リクエスト]をクリックすると、API GatewayとLambda関数がどのように連携されているかを確認することができます。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_16_s.png)
API Gatewayにはリクエストをどのようにハンドリングするかを決定するいくつかの「統合タイプ」が存在しますが、Lambda関数と連携する際は[Lambda関数]を選択します。
その中のオプションの一つとして「Lambdaプロキシ統合」というものが存在します。
![](http://cz-cdn.shoeisha.jp/static/images/article/10332/10332_17_s.png)
これを有効にすると統合タイプが「LAMBDA_PROXY」に、無効にすると「LAMBDA」となります。
統合タイプが「LAMBDA」の場合、リクエスト情報をLambda関数に渡すためのマッピングを明示的に設定する必要があり、またLambdaから返された結果を正規表現で検証し、適切なHTTPステータスコードを付与する必要があります。
その一方で、Lambda関数側は、API Gatewayでマッピングされた値がevent
引数で渡され、callback
で返却する値がそのままAPI Gatewayのレスポンスボディとなる、シンプルなものとなります。
対して統合タイプが「LAMBDA_PROXY」の場合は、API GatewayでのマッピングやHTTPステータスコードの設定が不要となりますが、コードの説明でも述べたようにstatusCode
、body
やheaders
などレスポンスに必要な情報を全てLambda関数の実行結果として返す必要があります。
「LAMBDA_PROXY」タイプには、以下のような制約が存在します。
-
レスポンスに必要な情報を全て
callback
の第二引数に渡す必要がある -
レスポンスの
body
はstring型である必要がある - Lambdaが返却する値の型が不正であったりエラーで終了した場合、必ずHTTPステータスコードが502のInternal Server Errorのレスポンスが返される
-
headers
の設定をLambda関数で行うため、API Gatewayの持つCORSの機能を用いることができない
「LAMBDA_PROXY」タイプは「LAMBDA」タイプと比較し、マッピングなどの複雑な設定を行うことなく利用することができますが、ステータスコードの適切な付与や、コード実行時のエラーハンドリングなどに考慮したコードを実装する必要があります。
単純なAPIであれば「LAMBDA」統合タイプを、複数のクエリパラメータを有していたり、リクエストヘッダーの情報を利用するような複雑なAPIの場合は「LAMBDA_PROXY」統合タイプを用いるといったように、APIの挙動に合わせて使い分けることをお勧めします。
まとめ
以上のように、AWSマネジメントコンソールのみを用いても、動的なAPIを簡単に作成することができます。
今回はリクエストに応じて動的なレスポンスを返す単純なAPIを作成しましたが、SESとS3 、Lambdaを組み合わせることで、ランディングページなどで使うお問い合わせフォームなども、別途Webサーバやデータベースなどを用意することなく、簡単かつ安価に作成することができます。
次回以降の連載では、AWSの上でサーバレスアーキテクチャを用いて、SPAを実装していきたいと思います。
参考URL
- ServerlessConf Tokyo 2016
- 「サーバーレスな事例が次々登場―ServerlessConf Tokyo 2016レポート」(Think IT)
- 「AWS Lambda and the Serverless Cloud」(Cloud Academy Blog)
- 「【翻訳記事】Google Cloud Functions 対 AWS Lambda: サーバーレスクラウドを制する闘いが始まる」(Qiita)
- 「サーバーレスアーキテクチャという技術分野についての簡単な調査」(Qiita)
- 「サーバーレス・アーキテクチャで構築したシステムの運用はどうやるのか?」(cloudpack.media)
- 「サーバーレスアーキテクチャとは何か? AWSの「Lambda」と「EC2」を比較して解説」(ビジネス+IT)