使用Serverless Framework来部署和调试AWS Lambda和API Gateway HTTP API

1,581 阅读4分钟

无服务器(Serverless)对开发人员来说应该是非常友好的架构,无须管理底层物理资源,操作系统配置、打补丁、弹性伸缩的配置统统不需要去操心了,只要专注在代码开发上,其他杂活都可以交由无服务器架构来完成,因此无服务器的应用自然更为流行

今天跟一个客户交流时他提到的一点我也感同深受:开发人员就是想要爽,代码写完一条命令可以在本地做调试,调试完一条命令可以直接把代码部署上去,爽!由于无服务器架构的特点,如果不在本地构建开发测试环境,每次都需要部署到云端再做调试,会非常不爽。另外自己打包代码,然后再手动上传到云端部署和配置也是非常繁琐。

最近研究了在AWS Serverless本地开发测试和部署相关的工具,包括AWS原生提供的开源工具AWS Serverless Application Model(SAM)和第三方Serverless.com提供的开源工具Serverless Framework Open Source 。充分感受到了部署和调试工具带来的爽!两个工具各有特色,其本质都是通过一个简化语法的模板文件(yaml),让用户来定义无服务器架构配置的一些细节,然后由工具自动对代码进行打包(包括安装相应的依赖包), 自动将该模板转换为一个Cloudformation的标准模板(相信我,Cloudformation模板不是给人看的,是给机器看的!) ,最后再将模板部署在AWS上面。如果有配置变更或代码变更,同样也由该工具重新打包上传代码,并利用Cloudformation的机制来进行整个配置的更新。

另外除了自动部署,这两个工具都提供了本地调试的方法,可以方便开发人员在自己电脑上把lambda代码跑起来,甚至可以在本地模拟api gateway,开发调试感觉就更爽了。

接下来就一起来尝试一下Serverless Framework:

安装

Serverless Framework提供了一个CLI工具(基于Node.js), 在本机安装好Node.js后,通过如下命令可安装Serverless Framework:

$ npm install -g serverless

初始化项目

通过如下命令创建一个基于python3模板的项目:

$ sls create --template aws-python3 --path sls-lambda-python3 
Serverless: Generating boilerplate...
Serverless: Generating boilerplate in "/Users/linjungz/projects/sandbox/sls-lambda-demo/sls-lambda-python3"
 _______                             __
|   _   .-----.----.--.--.-----.----|  .-----.-----.-----.
|   |___|  -__|   _|  |  |  -__|   _|  |  -__|__ --|__ --|
|____   |_____|__|  \___/|_____|__| |__|_____|_____|_____|
|   |   |             The Serverless Application Framework
|       |                           serverless.com, v1.67.3
 -------'

Serverless: Successfully generated boilerplate for template: "aws-python3"

模板配置

修改serverless.yml,指定AWS上部署的一些配置细节,包括部署的区域,命令行使用的profile等。如果不修改模板文件,也可以在部署时通过命令行参数提供。

provider:
  name: aws
  runtime: python3.8
  # Lambda部署的AWS区域
  region: cn-northwest-1
  # AWS CLI Profile
  profile: cnlab
functions:
  hello:
    handler: handler.hello
    # 在API Gateway中配置 HTTP API 来触发Lambda
    events:
      - httpApi: 'GET /'

修改handler.py:

import json
def hello(event, context):
    body = {
        "message": "Hello World AWS Serverless"
    }
    response = {
        "statusCode": 200,
        "body": json.dumps(body)
    }
    return response

部署与调试

接下来就可以进行部署:

$ sls deploy
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
........
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service sls-lambda-python3.zip file to S3 (390 B)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
..............................
Serverless: Stack update finished...
Service Information
service: sls-lambda-python3
stage: dev
region: cn-northwest-1
stack: sls-lambda-python3-dev
resources: 11
api keys:
  None
endpoints:
  GET - https://9ea7dptou3.execute-api.cn-northwest-1.amazonaws.com.cn/
functions:
  hello: sls-lambda-python3-dev-hello
layers:
  None
Serverless: Run the "serverless" command to setup monitoring, troubleshooting and testing.

可以看到lambda已经部署到AWS上,同时配置了API Gateway HTTP API,接下来可以测试一下这个接口:

$ curl https://9ea7dptou3.execute-api.cn-northwest-1.amazonaws.com.cn/
{"message": "Hello World AWS Serverless"}%   

查看Lambda执行的日志:

$ sls logs -f hello 
START RequestId: 11a21905-0c6b-453d-8386-6367e99494fa Version: $LATEST
Debug:  {'message': 'Hello World AWS Serverless'}
END RequestId: 11a21905-0c6b-453d-8386-6367e99494fa
REPORT RequestId: 11a21905-0c6b-453d-8386-6367e99494fa  Duration: 1.34 ms       Billed Duration: 100 ms       Memory Size: 1024 MB    Max Memory Used: 53 MB  Init Duration: 697.87 ms

修改代码中变量body的值,并在本地进行运行查看结果:

$ sls invoke local -f hello
Debug:  
{'message': 'Hello World AWS Serverless V2'}

{
    "statusCode": 200,
    "body": "{\"message\": \"Hello World AWS Serverless V2\"}"
}

可以看到本地运行结果已经更新,这时候使用 sls deploy 命令重新可以部署到云上并查看到返回结果已经更新。

使用 serverless-offline 插件进行本地调试

接下来我们尝试搭建本地的API Gateway + Lambda 的调试环境,需要安装Serverless Framework的一个插件: serverless-offline

$ sls plugin install --name serverless-offline
Serverless: Creating an empty package.json file in your service directory
Serverless: Installing plugin "serverless-offline@latest" (this might take a few seconds...)
Serverless: Successfully installed "serverless-offline@latest"

该命令会自动修改 serverless.yml 文件以启用这个插件

plugins:
  - serverless-offline

接着通过如下命令启用本地调试

$ sls offline
offline: Starting Offline: dev/cn-northwest-1.
offline: Offline [http for lambda] listening on http://localhost:3002

   ┌─────────────────────────────────────────────────────────────────────────┐
   │                                                                         │
   │   GET | http://localhost:3000/dev                                       │
   │   POST | http://localhost:3000/2015-03-31/functions/hello/invocations   │
   │                                                                         │
   └─────────────────────────────────────────────────────────────────────────┘

offline: [HTTP] server ready: http://localhost:3000 🚀
offline: 
offline: Enter "rp" to replay the last request

查看本地运行的结果:

$ curl http://localhost:3000/dev
{"message": "Hello World AWS Serverless V2"}%

同时可以看到sls offline也会实时显示相关的日志:

offline: GET /dev (λ: hello)
Debug:  {'message': 'Hello World AWS Serverless V2'}
offline: (λ: hello) RequestId: ck93gtjk40008ebs5dikdcq2m  Duration: 359.61 ms  Billed Duration: 400 ms

从上面的简单测试可以看到,Serverlss Framework在模板配置上相当精炼,同时本地调试也非常方便,关键CLI还是开源的,有非常多的plugin进行功能扩展,真是无服务器开发与部署的利器!

本文所使用的代码可参考如下链接: github.com/linjungz/sl…

注:观点仅代表个人