2018年7月13日金曜日

【AWS Lambda】API Gateway の疎通確認

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。

ただいま、Lambdaで関数作りを頑張っています。

試しに繋いでみるか

前回「【AWS Lambda】Webリクエストの受付」でひとまずAPI Gatewayをトリガーにくっつけました。

これでもうURLが存在しているのでアクセスしてみましょう。




  • {"message": "Internal server error"}

Internal server error!!

初期状態では動かない!!

テストでは正常

しかしですね、Lambdaのテストでは正常なんですよ。



テストでは正常なのに、実際にアクセスするとエラー。

ここで躓く人って結構多いんじゃないでしょうか?

私も苦労しました。

原因

実はですね、Lambdaのテストは「ラムダ関数だけ」のテストで、API Gatewayは関係無いんですよ。

つまり、上記の状況は

  • ラムダ関数は正常である。
  • API Gatewayでエラーを起こしている。

という状況なのです。

API Gatewayエラーの原因

API Gateway がエラーになる原因。

ログとかそういうの一切出ないですから!!

ネット調査で特定しました。



API Gatewayでは、以下の形式でレスポンスを返さなければいけないと書かれています。

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "body": "..."
}


関数

つまり、API Gatewayを通せるようにLambda関数を書かねばなりませんから。

def lambda_handler(event, context):
    # TODO implement
    return 'Hello from Lambda'

これを

def lambda_handler(event, context):
    # TODO implement
    return {
        "isBase64Encoded": False,
        "statusCode": 200,
        "headers": {},
        "body": "Hello from Lambda"
    }

こうする!!

結果

無事に表示されました。



これ、知らなけれ本当に意味分からないので、ここで躓かないよう注意して下さい。

続く

引き続きエAPI Gatewayの掘り下げを進みます。

2018年7月6日金曜日

【AWS Lambda】Webリクエストの受付

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近、AWSをフル活用して社内システムを作ったので、そのノウハウのご紹介を行っています。

ただいま、Lambdaで関数作りを頑張っています。

Webからのリクエストを受け付けたい!!

Lambda というのは実に色々な長所を持つ優れたアーキテクトですが、私が一番好きなのは、その可用性の高さです。

処理不可に応じて凄く細かい単位で柔軟にスケールアウトして行ってくれます。

この細かい単位でスケールアウトという性質が最も効果を発揮するのは、やはりWebだと思います。

Webというのは人気が無い時はアクセスゼロなのに、どこかで祭りが発生すると一気に数百万ヒットにまで到達することがあるくらいアクセス数が劇的に増減します。


  • Lambda はアクセス数の増減に最強である。


これが最大の長所だと思います。

と言うわけで、HTTPリクエストのトリガーを司る機能「ApiGateway」を見ていきましょう。



Amazon API Gateway概要

Amazon API Gateway は、正確にはLambdaの一部ではなく、Lambdaと連結するAWSの別サービスです。

公式サイトでは以下のように宣伝されています。


  • どのようなスケールであっても、簡単に API の作成、配布、保守、監視、保護が行えます。
  • バックエンドからのデータ、ビジネスロジック、機能にアクセスする、アプリケーションの玄関として振る舞う API を作成できます。
  • 最大数十万個の同時 API 呼び出しの受け入れと処理に伴うすべてのタスクを取り扱います。


が、この表現はどうにも分かり辛いです。AWSのサイトって何かピンと来ない言い回しをされていることが多いんですよね。


早い話、私はこの機能は「WebAPIのURLを疎結合に管理するサービス」だと理解しています。

例えばですね、WebAPIとして「https://www.genesis.com/user/get」というURLがあったとしますよね。

これ、最近はもうデファクトスタンダードになっているRails系規約で考えますと、このURLに相当する処理は「userクラスのgetメソッド」なんですよ。


  • クラス名+メソッド名 = URL


これが命名規約なんです。

でも悪い言い方をすれば、「クラス名・メソッド名とURLが密結合になっている」とも言えます。

内部の実装として都合の良い命名と、人様に向けて公開するURLのネーミングが同じとは限りません。


  • 本番系はこのURL
  • テスト系はこっちのURL


とか、

  • URLの変更に伴ってクラス名を変えなきゃいけなくなっちゃった。⇒大規模リファクタリング

みたいな要件、状況はあり得ますからね。
まあ、規約に頼らず手動でURLとクラスの紐づけを行うという手もありますが、それはそれでデザインパターンとして汚い。

だ・か・ら、


  • 実装チームは実装チームで、Lambdaの中で都合の良いように作ってください。
  • 公開するURLは別途、Amazon API Gatewayで設定します。


ということが可能な疎結合アーキテクトを実現する。

そこにAmazon API Gatewayの美しさがあると私は感じています。

まあ、APIの規模が小さい場合は「実装名=URL」で十分なので疎結合性の利点を感じられないのですが、いずれにせよAPI Gatewayを使わなければWebからLambdaを呼べないのだから、覚えるしかありません。


Lambda で API Gateway の設定

では、Lamda と API Gateway を繋げる設定をしていきましょう。

トリガー追加

まず、Lambdaのコンソール画面からトリガーで API Gateway を追加します。


トリガー設定

トリガーを追加するとすぐ下に設定項目が出てきます。


それぞれの意味はこちら。

  • API 名:API を一意にする為の名前。URLに含まれる。今回は「ApiGatewayTest」
  • デプロイされるステージ:APIを展開するステージ。URLに含まれる。今回は「prod」
  • セキュリティ:必要に応じて権限を付与。今回は全開放であるオープンで。

これで追加ボタンを押せば完了です。

結果、URLは以下のようになります。

  • https://xxxxx.amazonaws.com/prod/ApiGatewayTest

ステージ

ここで少し分かり辛いのは「ステージ」とは何かということです。

URLにも含まれていますね。
これはAPIのバージョン管理や、本番系とテスト系の切り分けに使うものです。

例えば、同じAPIでも「本番用」「総合テスト用」「結合テスト用」を分けて実行したい時、ステージの設定を分けることで簡単に制御出来るわけです。

  • prod ← productionの意
  • staging
  • test

と設定すれば、

  • https://xxxxx.amazonaws.com/prod/ApiGatewayTest
  • https://xxxxx.amazonaws.com/staging/ApiGatewayTest
  • https://xxxxx.amazonaws.com/test/ApiGatewayTest

となる。

分かり易いでしょ?


ステージが不要な場合

「ステージなんていらないから少しでもURLを短くしたい」と、ステージを省略したいというケースもあると思います。

「prod」なんてのは開発者視点のURLであって、一般ユーザから見れば本番以外に無いわけですから。
出来れば消したい。

しかしながら、これは出来ないんじゃないかと思います。
調査しましたが、出来そうな雰囲気が無い。。。

これはステージ名のネーミングセンスで乗り切るしか無いんじゃないかな……。

  • api

と設定すれば、

  • https://xxxxx.amazonaws.com/api/ApiGatewayTest

となるので、一見するとステージ名が露出しているのようには見えないでしょ?

セコい手ですが。。。

続く

今回はここまで。
API Gatewayはバージョン管理とかの機能もあるみたいなので、掘り下げていきたいと思います。