エンジニアレポート

AWS Lambda + API Gateway + S3 で簡易Webアプリケーションを作成

2019年10月03日

3回目の登場になりました、データスタジアムのエンジニア菅です。
(IaaSを使ったら負けだと思っています。)

1回目にAzure Functionを使ったサーバレスの記事を投稿しましたが、ここ1年くらいで他社様のサーバレス事例を耳にすることが多くなりました。そんなわけで、再度サーバレスのお話です。

背景

当社エンジニアの仕事の中で、「業務運用上必要な簡易Webアプリケーション(ツール)を用意する」ということが結構あります。オペレーション担当の方々がブラウザで簡便に操作できるようなツール類を開発することになるわけですが、今までは適当なオンプレのWebサーバで動作させることが大半でした。ただ最近は当社もクラウド化が進み、オンプレのサーバからEC2やAzure VMにシフトすることが増えてきました。

今回はさらに一歩すすんで、このようなツール類をサーバレスで用意してみることに挑戦してみました。

開発手順

以下のような流れで進めます。

  1. AWS Lambdaでツール本体を実装
  2. API Gatewayを設定する
  3. S3でHTMLをホスティング

詳細は割愛してポイントだけピックアップして説明します。

1. AWS Lambdaでツール本体を実装する

まずはツール本体の用意です。
今まではPHPやらRubyやらPythonやらでPGを書いてEC2上で動作させていましたが、AWS Lambdaで実装します。LambdaではPythonやNode.jsが使えますが、今回はPythonを使ってみました。

簡単なツールであれば、AWS Console上でそのままソースコードを編集することも可能です。 複雑なツールになる場合は、一度ローカルのPC環境などで実装したソースをLambdaにアップロードするのが良いでしょう。データベース上のデータ編集や仮想マシンの起動停止など、ツールによってどういう実装にするかは変わりますが、例としてHello World文字列をJSONで応答する関数を作成します。

まずはAWS ConsoleからLambdaの設定画面へ。

LambdaSetting01

ダッシュボードから関数の作成を選択します。

次に関数のタイプやランタイム、名前を設定します。

LambdaSetting02

ここでは、Hello Worldを作成しますので一から作成を選択し、適当な関数名を設定します。今回、ランタイムはPython3.7としています。

作成をクリックすると、以下のようなソースコードが自動で生成され、Lambda Functionの出きあがりです。

2. API Gatewayを設定する

次に1で用意したLamda functionをHTTPのREST APIで実行できるようにするため、API Gatewayを設定します。

AWS ConsoleからAPI Gatewayの設定画面に「REST」で「新しいAPI」を選択。適当なAPI名を設定します。

APIgwSetting01

作成されたREST APIにHTTPのメソッドの設定を追加します。

APIgwSetting02

とりあえず、GETで受けるようにするので、GETメソッドを追加です。

APIgwSetting03

GETメソッドを追加したら、統合ポイントとして、先ほど作成したLambda Functionを指定します。

APIgwSetting04

APIgwSetting05

これでGETメソッドがエンドポイントに実装されました。
テストをクリックすると実際にAPIの動作がテストできます。

APIgwSetting06

テストした結果、ステータス:200=正常にHTTPレスポンスが返って、先ほどのLambda Functionで指定したHello Worldの文字列がJSONで返っていることが分かります。

次に作成したAPIをデプロイして、実際にアクセス可能なURLをパブリッシュします。メソッドを作成したときと同様にアクションから、今度は「APIのデプロイ」を実行します。

APIgwSetting07

デプロイ先(ステージ)を選択しますが、最初は何もないので、新しいステージを作成します。適当なステージ名を設定します。

APIgwSetting07

余談ですが、ここでテスト用のステージを作成して本番用のステージと切り分けて、
一旦テスト用のステージにデプロイし動作確認してから、本番用のステージにデプロイ
のようなことができます。

よく考えられてますね!

デプロイが完了すると、URLが発行されます。

APIgwSetting08

このURLをブラウザから叩いてみると実際にAPIからLambda Functionが実行され、Hello WorldがJSONでブラウザに返ることが確認できます。これでAPI GatewayによりREST APIが完成しました。

3. Lambdaの非同期実行

API Gatewayまで用意できましたが、ここで一つ問題が。
作成したLambda Functionの実行時間(タイムアウトまでの時間)は1秒~15分までで設定できます。ある程度時間がかかる処理の場合は、5分などに設定しておきますが、これを呼び出すAPI Gateway側のタイムアウトは最長で29秒です。

なので、API Gateway経由でLambda Functionを実行した場合、Lambda Function側の処理が続いている(応答待ち)にも関わらず、29秒を過ぎるとAPI Gatewayのタイムアウトとなり、呼び出し元にTimeoutでエラーを返してしまいます。

うーん、これは困った。。。

いろいろと解決方法はあるみたいですが、今回は以下のような方法を取ってみました。

Architecture

まず、作成したLambda Function(A)を非同期で実行する別のLambda Function(B)を作成します。Bの実装は簡単で、自身が呼び出されると対象のLambda Functionを非同期呼び出しして、自身はすぐに呼び出し元に応答を返します。

以下、Node.jsでの実装例です。

API Gateway側では、上記Bのfunctionを呼び出すようにします。

これで、もともとの処理を実装していたAが29秒以上処理に時間がかかっても実処理は最後まで実行されます。

※細部まで丁寧に実装するなら、Aの処理完了をチェックする、別のLambda Functionを用意する必要がありますが、今回は割愛します。

4. S3でHTMLをホスティング

これでほぼツールは完成です。
最後にツールを叩くための画面を用意しますが、これもサーバレスで。

一番お手軽な、HTML+javaScriptでAPI Gatewayの該当I/FをAjaxリクエストで実行する画面を作ります。

そして、上記ファイルをS3にアップロードし適切な権限を設定し、公開しておきます。

後は、S3の公開URLを周知すれば完了です。

ちなみに、接続元IPアドレス制限なんかもできます。

時代はサーバレス?

サーバレスアーキテクチャを始めとして、なるべくIaaSを使わない、PaaSやマネージドサービスを使うという方針を、AWSや各クラウド事業者も推奨しているようです。

サーバレスの利点はいろいろとありますが、開発者(開発チーム)としては、リソースをアプリケーションに集中できる点が最大の魅力だと思います。

オンプレの時代は1つのWebサービスを作るのに、インフラ部分から考えるとサーバー調達から始まり、ネットワーク、OS、ミドルウェアと、アプリケーション開発以前のタスクがたくさんあったわけです。

それが、IaaSを使えるようになると、OS以下のレイヤは気にしなくても良くなりました。ただし、ミドルウェアやセキュリティ対応(OSなどのパッチ)、冗長性の確保といった課題は引き続き対応するべきタスクとして残ります。

ここで、マネージドサービス(サーバレスアーキテクチャ)を導入すると、もはや開発者(チーム)のタスクはほぼ90%アプリに集中できることになります。サーバレスやマネージドサービスならミドルウェアのことなんか考える必要はないですし、冗長性も担保された形で提供されています。AWS Lambdaなんかでも、実行するAvailability Zoneを冗長化して割り当てるだけでOKです。

もちろんなんでもかんでもサーバレスというのは、向き不向きもありますから考えないといけないですが、サーバレスorマネージドサービスが適用できるところは積極的に利用していって損はないと考えております。

やっぱり、IaaSを使ったら負けです。

参考

AWSでAPI Gatewayから非同期でLambdaを起動してS3にファイルアップロードしようとしたらハマった話。 By Takehiro Suemitsu様

エンジニア募集中!

データスタジアムでは一緒に働いていただけるエンジニアを募集しています。野球、サッカー、バスケなどスポーツが好きな方であれば、とても面白い仕事ができる会社です。興味を持たれた方はぜひこちらをご覧ください。

エンジニアトップ エンジニアインタビュー エンジニアレポート

  • 採用情報
  • おしらせ
  • 掲載事例

ページトップヘ