皆さん、パブリッククラウド使ってますか。
無料利用枠があるサービスもあるので、個人で使っているという方も多いのではないでしょうか。

かくいう私もその1人です。
今回はその中から、Amazon Web Services(AWS)を利用したサーバーレスアプリケーションの作成について紹介します。

今回利用したサービス

  • API Gateway
  • Lambda
  • DynamoDB

作成したもの

処理の流れ

  1. API Gatewayで作成したエンドポイントをクライアントがコール
  2. API GatewayがLamdba関数を実行
  3. Lamdba関数内でDynamoDBのデータを取得し、呼び出し元(API Gateway)へ返却
  4. API Gatewayがクライアントへデータを返却

手順

アカウント登録

何をするにもアカウント登録しなければ始まりません。
手順はこちらをご覧ください。

登録後12ヶ月の無料利用枠があり、この間はほとんどのサービスが無料で利用できます。
にもかかわらずクレジットカードを登録するというのはやっぱり気になるところではありますが、 従量課金という仕組み上(12ヶ月中であっても有料サービスを使えば課金が発生するため)やむを得ないのでしょうね。

なお、今回利用するリージョンはいずれも「ap-northeast-1」です。

IAM(Identity and Access Management)ユーザ登録

IAMは、ユーザに適切な権限を割り振って管理するための仕組みです。
今回は必須ではありませんが、登録時のルートアカウントを使い続けるのはセキュリティ的にお勧めされていないので、AWSを利用するなら作成しておいたほうが良いです(IAM自体は12ヶ月の無料利用枠後も無料で利用できます)。
「サービス」→「IAM」→「ユーザー」→「ユーザーの追加」で作成できます。
※ユーザーの作成およびポリシーの設定については本筋ではないので省略します。

テーブル作成(DynamoDB)

DynamoDBは、最近何かと話題のNoSQLデータベースです。
管理コンソールより「DynamoDB」→「テーブルの作成」でテーブルを作成します。
今回は以下のように定義しました。

  • テーブル名:categories
  • プライマリパーティションキー:category(文字列)
  • プライマリソートキー:sortOrder(数値)

NoSQLデータベースなのでキー以外は自由に設定できますが、今回はとりあえず「message(文字列)」というフィールドに表示したいメッセージを格納します。

関数作成(Lambda)

Lambdaは、指定したイベントが発生したときのみ動作する(=常時稼働しない)サービスです。
管理コンソールより「Lambda」→「関数の作成」→「一から作成」で作成します。
「カスタムロールの作成」を選択し、Lambda実行用のIAMロールを作成します。

なお、今回はこのIAMロールに「AmazonDynamoDBReadOnlyAccess」ポリシーを付与する必要があります。
管理コンソールより「IAM」→「ロール」→「上記で生成したロール名」を選択→「ポリシーのアタッチ」で上記をアタッチしてください。

言語は色々使えるのですが、今回はPython3.6を使いました。
以下のコードを入力し「保存してテスト」で関数をテストします。

# lambda.py
def lambda_handler(event, context):
    from datetime import datetime, timezone, timedelta
    now = datetime.now(timezone(timedelta(hours=+9), 'JST'))
    return {
        'date': '{0:%Y-%m-%d %H:%M:%S}'.format(now),
        'items': get_message(event),
    }

def get_message(event):
    import boto3
    from boto3.dynamodb.conditions import Key

    dynamodb = boto3.resource('dynamodb')
    table = dynamodb.Table('categories')
    return table.get_item(Key={
        'category': event['category'],
        'sortOrder': int(event['order']),
    })['Item']

Lambda関数が呼び出された際、まずlambda_handlerが実行されます。
引数eventにパラメータが格納されるので、それを利用してDynamoDBから値を取得します。

エンドポイント作成(API Gateway)

API Gatewayは、APIのエンドポイントを作成できるサービスです。
実際の処理は今回のようにLamdbaでも良いですし、他のAWSサービスでも良いです(もちろん、HTTPサービスもコールできます)。
管理コンソールより「Amazon API Gateway」→「APIの作成」を選択し、APIを作成します。
その後、実行するメソッドを追加します。

今回はデータを返却するだけなので「GET」のみ作成しました。
セットアップでは「統合タイプ」に「Lambda関数」を選択し、先ほど作成した関数のリージョンと名前を選択します。
なお、Lambdaにパラメータを渡すためには、統合リクエストを編集する必要があります。

「統合リクエスト」を選択し、「本文マッピングテンプレート」→「マッピングテンプレートの追加」で以下を入力して保存します。

最後に「アクション」から「APIのデプロイ」を選択し、ステージを決定のうえデプロイ完了です。
ステージエディターの「URLの呼び出し」横にあるURLが今回利用するエンドポイントです。

呼び出しは以下のようになります。

https://(エンドポイントURL)/(ステージ名)?category=(テーブルのcategory)&order=(テーブルのsortOrder)

できあがったもの

かなり駆け足、かつ途中端折っている部分もありますが、いかがでしたでしょうか。

所感

正直「こんなに簡単に実装できるのか」と衝撃でした。
IAMやLambda関数を利用したAPI認証も可能なので、モバイルサービスやSPAと連携したAPIも低コストで構築できるのではないでしょうか。
Lamdbaは常時稼働でない分、初回起動時の速度をいかに担保するかが重要に感じました。
今回の件と直接は関係ありませんが、IAMユーザはポリシー割り当てで結構ハマったので、そのあたりは次回以降に書きたいと思います。

ちなみに、これらの機能を使った別のアプリケーションをこちらに公開していますので、興味のある方はご覧ください。