Amazon API GatewayとLambdaを利用したサーバレスなWebアプリを作ってみた

こんぴてんしーせんたーのisaです。

流行っているサーバレスアーキテクチャを利用して、弊社で提供しているBeaconBridgeと連動するWebアプリケーションを作ってみました。

目的は、7月にAmazonからAPI Gatewayが発表され、Web上にAWS Lambda + API Gatewayを利用したサーバレスアーキテクチャのサンプルが多数公開されていますが、実際に使ってみないと使い方や特徴が掴めないと思い、お試しでそれらを組み合わせてWebアプリケーションを作ってみました。

今回はその備忘録の意味も込めて記事を書きました。


サーバレスアーキテクチャ

まず、サーバレスアーキテクチャですが、Web/アプリケーションサーバを利用せずに、Webサービスを構築するというものです。
GoogleのGoogle App Engine(GAE)が先駆けとなり、最近ではAWSでも前述のLambda、API Gatewayを利用することで、このアーキテクチャを採用することができるようになりました。

サーバレスを採用する効果

次のような事がサーバレスアーキテクチャを採用する事で得られる効果だと言われています。

  • インフラのリソースや可用性をサービス提供(GoogleやAmazon)側で保証してくれるため、アプリケーション開発に集中可能
  • インフラのランニングコスト(仮想サーバ代、運用コスト)が削減可能

Lambda と API Gateway

Lambda

特定のイベントをトリガにAWS Lambdaにアップロードしたコード(Node.js/Java/Python)を実行させるコンピューティングサービス。
例えばDB更新をトリガに通知メッセージを出すなど、AWS上の各種サービスリソース同士を柔軟に結びつけることができます。

AWS Lambdaの詳細は下記をどうぞ
https://aws.amazon.com/jp/lambda/details/

API Gateway

Amazon等のクラウドのサービスをREST APIとして公開できるものにしたサービスです。
API Gatewayを利用することで、AWS Lambda で稼働しているコードをREST APIとして公開できるようになりました。

これにより、任意のWebアプリケーションからAPI Gatewayで作成したAPIを実行することで、Amazonが提供するWebサービス(例えばDynamoDB)に簡単に利用できるようになりました。
(今まではAWS SDKを利用する必要があり、なかなか大変だった)

API Gatewayの詳細は下記をどうぞ
https://aws.amazon.com/jp/api-gateway/

作成したWebアプリケーションの構成

アプリケーションは下記を組み合わせた構成としています。

  • API Gateway
  • Lambda
  • S3(HTML + JavaScript)
  • DynamoDB

img_cresco_enginner_blog

構成自体は良くあるものだと思います。
動きは次のような形になります。

BeaconBridge ⇔ DynamoDB連携
  1. BeaconBridge から ビーコン検出トリガで WebHook( API Gateway 叩く )
  2. WebHookトリガで API Gateway がLambdaを起動
  3. Lambda から DynamoDB ( WebHookのパラメータをパースして必要な情報を格納 )
静的サイト ⇔ DynamoDB 連携
  1. S3 に配置した静的サイト(HTML)を取得
  2. HTML に記載されている JavaScript から API Gateway を叩く
  3. Lambda から DynamoDB にクエリをかけ、結果をレスポンスに載せる
  4. API Gateway からのレスポンスで DOM操作( コンテンツ更新 )

実装時に注意点

DynamoDBを利用するためのSDK

DynamoDBを利用するためのSDKには次の2種があります。

  • AWS SDK
  • DynamoDB Document SDK

サンプルとしてWebサイトに公開されているものの多くは「AWS SDK」を利用したものです。
しかし、AWS上で新規のLambda用のコードを作成するときに選択できるサンプルコード集(blueprint)には、「DynamoDB Document SDK」が利用されています。

この2種のSDKに互換性があれば問題ないのですが、putやquery時のパラメータに、valueの型が必須/不要といった差があり、間違うと当然エラーになります。
(参照するドキュメントにはご注意を!これにハマってそこそこ時間取られました…)

AWS SDKを利用した場合の例(put)

var AWS = require(‘aws-sdk’);
var dynamodb = new AWS.DynamoDB({region: ‘ap-northeast-1’});

// put用パラメータ
var param = {
TableName: ‘your-table-name’,
Item: {
‘user’:{ “S” : “hogehoge” }, // 文字列型を指定
‘id’ :{ “N” : “1” } // 数値型を指定
}
};
dynamodb.putItem(param, function (err, data) {
});

DynamoDB Document SDKを利用した場合の例(put)

var doc = require(‘dynamodb-doc’);
var dynamodb = new doc.DynamoDB();

// put用パラメータ
var param = {
TableName: ‘your-table-name’,
Item: {
‘user’: ‘hogehoge’,
‘id’ : 1
}
};
dynamodb.putItem(param, function (err, data) {
});

IAM権限

ユーザのAWSの各種サービス利用権限を絞るために、IAM(Identity and Access Management)を利用します。
IAMでLambdaやDynamoDB、API Gatewayの利用を許可していても、Lambdaの実装が進められないという罠がありました。

Lambdaにサービスの利用権限を付与しなければならない為、IAMを利用するための権限も必要という事でした。
ルートアカウントやIAMで全てのサービスを許可されていると気が付きにくい点です。

まとめ

利用してみた感想

  • インフラ構築が不要になったことで開発者がアプリケーション実装に専念できる
  • 小規模なWebアプリケーションならば短期で実装できる
  • 従量課金制なので使っていなくても無駄にならない
  • リアルタイムWebアプリケーションには不向きだと思われる
  • ドキュメントの整備は、もう一歩進んでほしい

継続調査したい事

  • パフォーマンスやスケーラビリティ(AWSが保証してくれるけど、どの程度なのか)
  • Cognito等を利用したAPIの認証(今回はお試しなので未考慮だった)
  • 既存システムのサーバーレスへの置き換え
  • Node.js以外を利用したLambdaの実装

SNSでもご購読できます。