aws serverless使用过程的一些整理

最近也用了aws lambda一段时间了。学习到了一些东西,这里整理一些。
lambda是采用函数的方式进行调用,背后不需要服务器,需要多少资源进行申请调整即可。但是如果只有lambda函数,就好比你写了一个python函数一样,外界不可调用,这个时候需要把lambda和api gateway给连接起来,这样你就可以通过url传递参数的方式来调用lambda函数,当然你可以通过lambda函数来进行数据库的操作,s3以及其他服务的操作。这里需要注意的时候,如果你调用其他的资源,你是需要给当前的角色增加操作其他服务的权限的。

当然,如果想把lambda和api gateway给穿起来,你可以通过图形化界面点击的方式来做。也可以通过自行写aws-cli命令脚本的方式来做,但是时间长了总是会不那么便捷。这个时候你可以使用sam. sam基于cloudFormation, cloudFormation就是通过配置脚本的方式来开启你所需要的资源。而sam特别针对的是无服务器这一块的,也就是你通过配置template.yaml脚本就可以实现lambda与api gateway的连接,通过很容易的命令行进行部署。sam一些常用的命令我这里粘贴一下:

sam init  // 初始化项目
sam local start-api // 本地起一个api服务

sam build  // 对代码进行打包
sam deploy --guided // 发布上线
 

sam的模板大概是这个样子:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description:   "get country code latest"
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
  Function:
    Timeout: 30

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
    Properties:
      CodeUri: countrylatest/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        HelloWorld:
          Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
          Properties:
            Path: /country/{countryCode}/latest
            Method: get

通过sam init可以生成这个文件,但是api的配置和codeUri的配置是需要你根据实际情况来调整的。这里Path:{countryCode}是不确定的,就是是通过请求传入的值来确定的,比如请求的是:
/country/cn/latest
那么countryCode就是cn.
那lambda那边如何获取到这个值呢?

    const countryCode= event.pathParameters.countryCode;   // 这个是获取路径里面countryCode的值的。
    const country = event.headers.country;  // 这个是获取headers里面的country的值的。
    const open_time = event.queryStringParameters.open_time;  // 这个是获取传递的参数open_time的值的。

这样的话,就可以获取api gateway传递过来的值了。
当然,如果你需要写很多的函数,但是函数某一部分又是公用的,你会用到layer. 即lambda里面层的概念,就是把公共的,大家都用的函数给抽取出来,然后放到layer层上去。这个可以参考官网的链接

https://amazonaws-china.com/cn/blogs/china/use-aws-lambda-layer-function/

因为我当前在尝试nodejs来做后端,所有可能和python有一些出入,需要参考

https://medium.com/@anjanava.biswas/nodejs-runtime-environment-with-aws-lambda-layers-f3914613e20e

最关键的需要注意的地方就是如果使用layer进行共用库函数的导入,比如你的公共文件名是tool.js,里面有一个helloworld方法 . 你需要使用let tool = require("/opt/tool");然后就可以通过tool.helloworld()的方法来进行调用。公共库函数要想上传,是需要打包成zip文件进行上传的。如果里面的函数如果想暴漏给外部进行使用,需要用到modules.exports. 给个case吧

const helloworld = ()=>{
	return 1;
}
modules.exports = {
	helloworld:helloworld
}

如果库函数是这样的话,外部通过引入/opt/tool文件,然后就可以使用tool.helloworld方法。

let tool = require("/opt/tool");
tool.helloworld();

写到这里,大部分东西都已经介绍过了,如果使用了dynamoDB数据库,很重要的就是它的表设计,这个要根据业务需求进行设计。弄清楚partitionKey和sortKey. 然后根据查询的需要去添加二级索引,尽量不要用扫描的方式。dynamoDB存储的方式会要求你采用类似{“hello”:{S:“123”},“world”:{N:1}}的方式进行存储,就是要标明每一种类型。如果你需要存储的数据是类似列表里面很多字典(对象),很复杂的嵌套方式的那种,目前可以采用的方式是转成JSON字符串,否则存储的时候可能会遇到一些问题。还有一点,dynamoDB存储的数据不让存储空字符串。你可以存储之前先过滤一遍。例如:

var removeEmptyStringElements = obj=>{
      for (var prop in obj) {
        if (typeof obj[prop] === 'object') {// dive deeper in
          removeEmptyStringElements(obj[prop]);
        } else if(obj[prop] === '') {// delete elements that are empty strings
          delete obj[prop];
        }
      }
      return obj;
    }

如果使用到事务的话,需要注意的是,如果使用的是从上图dynamoDB = new AWS.dynamoDB.DocumentClient(),需要使用dynamoDB.transactWrite, 如果使用的是 dynamoDB = new AWS.DynamoDB(),需要使用dynamoDB.transactWriteItems. dynamoDB.DocumentClient和DynamoDB所包含的方法是完全不一样的,而且传递的参数也略有不同,比如dynamoDB.DocumentClient 在插入数据的时候,用的是put方法,插入的数据是不需要标明参数类型的。例如:
Item:{"user":123,"word":123456}
但如果你使用的是DynamoDB, 需要标明类型。例如:
Item:{user:{S:"2010", N:"10"}]}
具体可参考:

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#putItem-property
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#put-property

当然,选用那种比较好的问题,我也找了一下,documentClient用起来更方便,但是当我们需要用到一些不太常规操作的时候,比如创建表,或者不只是增删改查的操作的时候,还是使用常规的DynamoDB会更好。详细见:

https://stackoverflow.com/questions/57804745/difference-between-aws-sdk-dynamodb-client-and-documentclient

参考:

https://stackoverflow.com/questions/53902670/dynamodb-transactwriteitems-is-not-a-function-error-on-lambda-but-not-when-using
https://medium.com/@anjanava.biswas/nodejs-runtime-environment-with-aws-lambda-layers-f3914613e20e
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB.html#putItem-property
https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/DynamoDB/DocumentClient.html#put-property
https://stackoverflow.com/questions/57804745/difference-between-aws-sdk-dynamodb-client-and-documentclient

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章