最近也用了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