Lambda-DynamoDB + API Gateway + Serverless Framework 的简单实例(Centos7)


之前的例子中,通过Sls简单生成了 Lambda 函数,
接下来,实例学习 DynamoDB 和 API Gateway 的联动。

应用示意图

客户端通过http访问 aws api 网关;
网关触发 lambda 函数;
函数将一些内容写入 dynamoDB;
serverless实现客户端的 deploy
Lambda-DynamoDB + API Gateway + Serverless Framework 的简单实例(Centos7)

SLS的结构生成

参照之前的例子生成 SLS 应用的结构: 使用Serverless构建无服务器应用.

DynamoDB生成

在 serverless.yml 内
添加 resources 部分,生成 sls-user 表,主key是 id

[[email protected] sampleSls]$ cat serverless.yml

service: sampleSls
provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: ap-northeast-1

functions:
  hello:
    handler: handler.hello

resources:
  Resources:
    DemoDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: S
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
        TableName: sls-user

DynamoDB生成确认

[[email protected] sampleSls]$ sls deploy -v
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service .zip file to S3 (387 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
......

可以通过console确认 DynamoDB 已经被生成

DynamoDB的表里添加数据

$ aws dynamodb put-item --table-name sls-user --item '{"id": {"S": "001"}, "name": {"S": "test01"}}' --region ap-northeast-1
$ aws dynamodb put-item --table-name sls-user --item '{"id": {"S": "002"}, "name": {"S": "test02"}}' --region ap-northeast-1
$ aws dynamodb put-item --table-name sls-user --item '{"id": {"S": "003"}, "name": {"S": "test03"}}' --region ap-northeast-1

Lambda-DynamoDB + API Gateway + Serverless Framework 的简单实例(Centos7)

DynamoDB + API-Gateway 读取数据测试

读取数据的用户角色权限追加

通过Lambda函数连接DynamoDB读取数据时,需要设置用户权限
在 serverless.yml 内
添加 iamRoleStatements 部分

[[email protected] sampleSls]$ cat serverless.yml

service: sampleSls
provider:
  name: aws
  runtime: nodejs8.10
  stage: dev
  region: ap-northeast-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:*
      Resource: "*"

functions:
  hello:
    handler: handler.hello

resources:
  Resources:
    DemoDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: S
        KeySchema:
          -
            AttributeName: id
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 5
          WriteCapacityUnits: 5
        TableName: sls-user

安装开发组件

添加 listUser 函数,取出DB内容

[[email protected] sampleSls]$ sudo npm install aws-sdk

修改NodeJs函数内容

[[email protected] sampleSls]$ cat handler.js
'use strict';

module.exports.hello = async (event, context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless v1.0! Your function executed successfully!',
      input: event,
    }),
  };

  // Use this code if you don't use the http event with the LAMBDA-PROXY integration
  // return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
var AWS = require("aws-sdk");
var getDynamoClient = function (event) {
    var dynamodb = null;
    if ("isOffline" in event && event.isOffline) {
        dynamodb = new AWS.DynamoDB.DocumentClient({
            region: "localhost",
            endpoint: "http://localhost:8000"
        });
    } else {
        dynamodb = new AWS.DynamoDB.DocumentClient();
    }
    return dynamodb;
}
module.exports.listUser = function (event, context, callback) {
    console.log("Received event:", JSON.stringify(event, null, 2));
    console.log("Received context:", JSON.stringify(context, null, 2));

    var dynamodb = getDynamoClient(event);
    var params   = { TableName: "sls-user" };

    dynamodb.scan(params, function(err, data) {
        var response = {statusCode: null, body: null};
        if (err) {
            console.log(err);
            response.statusCode = 500;
            response.body = {code: 500, message: "ScanItem Error"};
        } else if ("Items" in data) {
            response.statusCode = 200;
            response.body = JSON.stringify({users: data["Items"]});
        }
        callback(null, response);
    });
};

yml内添加函数定义

serverless.yml内添加 listUser 函数的定义
定义 path 和 get方法(API-Gateway)

functions:
  hello:
    handler: handler.hello
  listUser:
    handler: handler.listUser
    events:
      - http:
           path: user
           method: get

deploy

[[email protected] sampleSls]$ sls deploy -v
......
......
Serverless: Stack update finished...
Service Information
service: sampleSls
stage: dev
region: ap-northeast-1
stack: sampleSls-dev
api keys:
  None
endpoints:
  GET - https://di9d8qo03k.execute-api.ap-northeast-1.amazonaws.com/dev/user
functions:
  hello: sampleSls-dev-hello
  listUser: sampleSls-dev-listUser
layers:
  None

可以看到,生成了 endpoint,
①浏览器直接访问,数据取得确认。
②命令执行

[[email protected] sampleSls]$ sls invoke -f listUser
{
    "statusCode": 200,
    "body": "{\"users\":[{\"id\":\"001\",\"name\":\"test01\"},{\"id\":\"003\",\"name\":\"test03\"},{\"id\":\"002\",\"name\":\"test02\"}]}"
}

或者

[[email protected] sampleSls]$ curl https://di9d8qo03k.execute-api.ap-northeast-1.amazonaws.com/dev/user

环境删除

[[email protected] sampleSls]$ sls remove -v