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

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