【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第2章 〜API Gateway利用編〜
あらすじ
今年も花粉が凄いですね。自分はずっと微熱出てる状況です。
会社にジョインしてから、もう2年くらい経ちました。
今回からは少し話題になっている「サーバーレスアーキテクチャ」というネタをシリーズで公開したいと思います。
※後々、リクエストに応じて更新することが多いのでストックしておくことをおすすめします。
自分は某社でCTOをしていますが、頭でっかちに理論ばっかり学習するよりは、イメージがなんとなく掴めるように学習し、実践の中で知識を深めていく方が効率的に学習出来ると考えています。
教育スタイルとしては正しい事をきっちりかっちり教えるのではなく、未経験レベルの人がなんとなく掴めるように、資料を構成していきます。
以下のようなシリーズネタで進めます。
| No. | 記事 |
|---|---|
| 1 | 【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第1章 〜nodejsのtemplate利用編〜 |
| 2 | 【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第2章 〜API Gateway利用編〜 |
| 3 | [【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第3章 〜DynamoDB利用編〜] |
では、今回もはじめていきましょう!
はじめに
今回は前回【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第1章 〜nodejsのtemplate利用編〜の記事と同様、serverlessのnodejsのtemplateを用いてAWS APIGatewayのエンドポイントを利用するにしてみましょう。
でははじめましょう
環境
Mac環境
10.11.6 node環境
$ nodebrew ls v0.12.14 $ nodebrew install-binary v7.4.0 $ nodebrew ls v0.12.14 v7.4.0 python環境
$ pyenv versions system 2.7.12 $ pyenv install -v 3.5.2 $ eval "$(pyenv init -)" $ pyenv shell 3.5.2 $ python --version Python 3.5.2 awscli環境
$ pip install awscli $ aws --version aws-cli/1.11.9 Python/2.7.10 Darwin/15.6.0 botocore/1.4.66 serverless環境
$ npm install serverless -g $ serverless --version 1.5.1 プロジェクト作成
前回【サーバーレスアーキテクチャ】をserverlessフレームワークで試す第1章 〜nodejsのtemplate利用編〜で作った「serverlesstest」というAWSプロファイルを引続き利用する形ですすめます。
いつも通り、serverlessコマンドでnodejsでapigatewayというプロジェクトを作って見ましょう。
$ serverless create --template aws-nodejs --provider aws --profile serverlesstest --path apigateway --verbose 作成されたプロジェクト
apigateway ├── handler.js └── serverless.yml API Gatewayを利用する
設定変更
$ cd ~/Documents/apigateway $ ls . handler.js serverless.yml LambdaのステージをtestにデフォルトのテストスクリプトをAPI Gateway経由で利用してみましょう。
変更箇所は以下の通りです。
今回からはdiffの結果を表示する形で楽しようと思います。
最初はイメージわかないと思うので、最終のファイル状況も併記しておきます。
--- serverless.yml.before 2017-03-06 18:26:48.000000000 +0900 +++ serverless.yml.after 2017-03-06 19:00:41.000000000 +0900 @@ -20,6 +20,9 @@ provider: name: aws runtime: nodejs4.3 + profile: serverlesstest + stage: test + region: ap-northeast-1 # you can overwrite defaults here # stage: dev @@ -56,7 +59,12 @@ functions: hello: handler: handler.hello - + events: + - http: + path: hello + method: get + cors: true + # The following are a few example events you can configure # NOTE: Please make sure to change your handler code to work with those events # Check the event documentation for details 変更後のファイル(変更箇所だけを抜粋)
provider: name: aws runtime: nodejs4.3 profile: serverlesstest stage: test region: ap-northeast-1 functions: hello: handler: handler.hello events: - http: path: hello method: get cors: true デプロイ
修正が完了したら、デプロイをしてみましょう。
$ serverless deploy --provider aws --profile serverlesstest -v デプロイが上手く行くと以下のようなインフォメーションが表示されるので
endpointsという箇所のURLをコピーしましょう。
API GateWayの情報を確認する。
Service Information service: apigateway stage: test region: ap-northeast-1 api keys: None endpoints: GET - https://xxxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/hello functions: apigateway-test-hello: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxx:function:apigateway-test-hello Stack Outputs HelloLambdaFunctionArn: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxx:function:apigateway-test-hello HelloLambdaFunctionQualifiedArn: arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxxxx:function:apigateway-test-hello:1 ServiceEndpoint: https://xxxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test ServerlessDeploymentBucketName: apigateway-test-xxxxxxxxxxxxxx ブラウザでアクセスしてみる
さきほどコピーしたエンドポイントのURLにブラウザでアクセスしてみましょう
以下の画像のように表示されれば成功です。
少しフライングしてDynamoDBにもアクセスしてみる
次回にDynamoDBにアクセスするRestfulなAPIを作る予定でしたが
少しフライングして、この回でもDynamoDBにアクセスして結果を読み取るようにしてみましょう。
いつも通り解説はほどほどに。
serverless.ymlを使って
- Lambdaで実行するユーザーにDynamoDBの周りの権限を付与(iamRoleStatementsらへん)
- resourcesでDynamoDBの設定も同時に設定
を設定しています。
serverless.ymlを変更する
--- serverless.yml.before 2017-03-06 19:00:41.000000000 +0900 +++ serverless.yml.after 2017-03-07 10:52:00.000000000 +0900 @@ -23,6 +23,17 @@ profile: serverlesstest stage: test region: ap-northeast-1 + iamRoleStatements: + - Effect: Allow + Action: + - dynamodb:DescribeTable + - dynamodb:Query + - dynamodb:Scan + - dynamodb:GetItem + - dynamodb:PutItem + - dynamodb:UpdateItem + - dynamodb:DeleteItem + Resource: "arn:aws:dynamodb:ap-northeast-1:*:*" # you can overwrite defaults here # stage: dev @@ -57,14 +68,14 @@ # - exclude-me-dir/** functions: - hello: - handler: handler.hello + readAll: + handler: handler.readAll events: - http: - path: hello + path: members method: get cors: true - + # The following are a few example events you can configure # NOTE: Please make sure to change your handler code to work with those events # Check the event documentation for details @@ -95,3 +106,21 @@ # NewOutput: # Description: "Description for the output" # Value: "Some output value" +resources: + Resources: + MembersDynamoDbTable: + Type: 'AWS::DynamoDB::Table' + DeletionPolicy: Retain + Properties: + AttributeDefinitions: + - + AttributeName: id + AttributeType: S + KeySchema: + - + AttributeName: id + KeyType: HASH + ProvisionedThroughput: + ReadCapacityUnits: 1 + WriteCapacityUnits: 1 + TableName: 'members' handler.jsを変更する
次の章でDynamoDBを使ったRestfulなAPIを作ってみようと考えていましたが
たいしたレベルでもないので、フライングして今回の章でもDynamoDBにアクセスして
結果を取得するようなAPIを作ってみましょう。
--- handler.js.before 2017-03-06 14:47:50.000000000 +0900 +++ handler.js.after 2017-03-07 10:29:24.000000000 +0900 @@ -1,16 +1,17 @@ 'use strict'; -module.exports.hello = (event, context, callback) => { - const response = { - statusCode: 200, - body: JSON.stringify({ - message: 'Go Serverless v1.0! Your function executed successfully!', - input: event, - }), - }; +const membersReadAll = require('./members-read-all.js'); - callback(null, response); +module.exports.readAll = (event, context, callback) => { + membersReadAll(event, (error, result) => { + const response = { + statusCode: 200, + headers: { + "Access-Control-Allow-Origin" : "*" + }, + body: JSON.stringify(result), + }; - // Use this code if you don't use the http event with the LAMBDA-PROXY integration - // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event }); + context.succeed(response); + }); }; members-read-all.jsを作成する
nodejs用のaws-sdkのライブラリを使ってアクセスするスクリプトを作ってみましょう
単純にDynamoDBのmembersというテーブルに対してscanをした結果を取得するだけの
スクリプトです。
'use strict'; const AWS = require('aws-sdk'); const dynamoDb = new AWS.DynamoDB.DocumentClient(); module.exports = (event, callback) => { const params = { TableName: 'members', }; return dynamoDb.scan(params, (error, data) => { if (error) { callback(error); } callback(error, data.Items); }); }; ライブラリをインストールする
nodejsで使うライブラリをインストールしましょう。
今回はpackage.jsonなども使わずインストールしてます。
$ npm install aws-sdk --save これでプロジェクトフォルダの配下にnode_modulesが作成されて対象のライブラリが保存されました。
デプロイ
長かったですね。実際にデプロイしてみましょう。
$ serverless deploy --provider aws --profile serverlesstest -v デプロイ結果から、エンドポイントをコピーしブラウザからもアクセスしてみましょう。
https://xxxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/members
「[]」という結果が表示されましたか?
AWSコンソールからDynamoDBを確認する
DynamoDBにデータをいれる
データが空な事を確認するというのもつまらないので
AWSコンソール画面から手動でデータを登録してみましょう。
DynamoDBのテーブルに項目を作成
DynamoDBのテーブルにデータを登録
API Gateway経由でDynamoDBの結果を確認する
再度ブラウザで
https://xxxxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/members
にアクセスして、さきほど登録したDynamoDBの値が取得出来るか確認してみましょう。
編集後記
少しフライングしてDynamoDBまで連携させてみました。APIの結果を表示するところまでしかネタに含めなかったのでイマイチ実感がわかないと思いますが、余力のある人はAPIを利用する側も作ってみてください。
次回は、もう少しCRUDをRestfulな感じで対応出来るAPIを作ってみようと思います。
お楽しみに。




