使用无服务器框架创建和部署

可以使用无服务器框架创建和部署 AWS Lambda。它允许您创建 AWS Lambda 触发器,并通过创建所需的角色来部署触发器。无服务器框架允许以更简单的方式处理大型项目。所需的事件和资源都写在一个地方,只需几个命令即可在 AWS 控制台上部署完整功能。

在本章中,您将详细了解如何开始使用 AWS 无服务器框架。

使用 npm install 安装无服务器框架

首先,您需要先安装 nodejs。您可以按如下方式检查 nodejs −

Install Server

您必须使用以下命令使用 npm 包安装 serverless −

npm install -g serverless
Severless

npm 完成后,执行 serverless 命令,该命令显示用于创建和部署 AWS Lambda 函数的命令列表。观察下面给出的屏幕截图 −

Framework Command Framework Prompt

您也可以使用 sls 代替 serverless。 sls 是 serverless 的简写命令。

Shorthand

如果您需要有关命令 sls 的帮助,您可以使用以下命令 −

sls create --help
Help

要创建 serverless 框架,您必须遵循以下步骤 −

步骤 1

要开始使用 serverless 框架,我们需要添加凭证。通过此操作,您可以在 AWS 控制台中首先按如下方式添加用户 −

添加用户

步骤 2

单击下一步:权限按钮添加权限。您必须将现有策略或管理员访问权限附加到此用户。

设置权限 摘要评论

步骤 3

单击创建用户以添加用户。它将显示我们配置无服务器框架所需的访问密钥和密钥 −

创建用户

配置 AWS 无服务器框架

让我们看看如何配置 AWS 无服务器框架。您可以使用以下命令实现此目的 −

sls config credentials --provider aws --key accesskey --secret secretkey
Configure Framework

请注意,输入的凭据的详细信息,即访问密钥密钥存储在文件 /aws/credentials中。

首先,创建一个文件夹,用于存储项目文件。

创建文件夹

接下来,我们将在aws-serverless文件夹中开始工作。

使用无服务器创建 AWS Lambda框架

现在,让我们使用下面给出的步骤创建一个带有无服务器框架的 Lambda 函数 −

步骤 1

以下是无服务器 create 命令的详细信息 −

Create Command

步骤 2

现在,我们需要分配模板,如下所示 −

AWS-nodejs、aws-nodejs-typescript、aws-nodejs-ecma-script、aws-python、aws-python3、aws-groovy-gradle 等。

步骤 3

我们将使用 aws-nodejs 模板来创建我们的第一个使用无服务器框架的项目。相同目的的命令如下所示 −

sls create --template aws-nodejs
Nodejs

请注意,此命令为模板 aws-nodejs 创建了一个样板。

步骤 4

现在,打开在 IDE 中创建的文件夹。这里我们使用 Visual Studio 代码,文件夹结构如下 −

Visual Studio Framework

步骤 5

创建了 2 个文件:handler.jsServerless.yml

AWS Lambda 基本函数详细信息在 handler.js 中显示如下 −

'use strict';

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

   // 如果您不使用 LAMBDA-PROXY 集成的 http 事件,请使用此代码
   // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
};

此文件 Serverless.yml 具有无服务器框架的配置详细信息,如下所示−

# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config Examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
#    docs.serverless.com
#
# Happy Coding!
service: aws-nodejs # NOTE: update this with your service name

# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
# frameworkVersion: "=X.X.X"

provider:
 name: aws
 runtime: nodejs6.10

# you can overwrite defaults here
#  stage: dev
#  region: us-east-1

# you can add statements to the Lambda function's IAM Role here
#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"

# you can define service wide environment variables here
#  environment:
#    variable1: value1

# you can add packaging information here
#package:
#  include:
#    - include-me.js
#    - include-me-dir/**
#  exclude:
#    - exclude-me.js
#    - exclude-me-dir/**

functions:
 hello:
   handler: handler.hello

#    The following are a few example events you can configure
#    NOTE: Please make sure to change your handler code to work with those events
#    Check the event documentation for details
#    events:
#      - http:
#          path: users/create
#          method: get
#      - s3: ${env:BUCKET}
#      - schedule: rate(10 minutes)
#      - sns: greeter-topic
#      - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000
#      - alexaSkill: amzn1.ask.skill.xx-xx-xx-xx
#      - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx
#      - iot:
#          sql: "SELECT * FROM 'some_topic'"
#      - cloudwatchEvent:
#          event:
#            Example:
#              - "aws.ec2"
#            detail-type:
#              - "EC2 Instance State-change Notification"
#            detail:
#              state:
#                - pending
#      - cloudwatchLog: '/aws/lambda/hello'
#      - cognitoUserPool:
#          pool: MyUserPool
#          trigger: PreSignUp

#    Define function environment variables here
#    environment:
#      variable2: value2

# you can add CloudFormation resource templates here
#resources:
#  resources:
#    NewResource:
#      Type: AWS::S3::Bucket
#      Properties:
#        BucketName: my-new-bucket
#  Outputs:
#     NewOutput:
#       Description: "Description for the output"
#       Value: "Some output value"

现在,我们需要根据我们的要求在 serverless.yml 文件中添加更改。您可以使用下面给出的命令 −

您可以对 Service 使用以下命令 −

service: aws-nodejs # 注意:使用您的服务名称更新此项

现在,在此处更改服务并添加我们文件夹的名称,如下所示 −

service: aws-serverless # 注意:使用您的服务名称更新此项

提供商详细信息如下所示 −

provider:
   name: aws
   runtime: nodejs6.10

提供商是 aws,运行时是 nodejs6.10。我们需要添加我们将在其中工作的 regionstage,即项目的 dev 或 prod 环境。因此,以下是更新后的 provider:provider 详细信息 −

name: aws
runtime: nodejs6.10
# you can overwrite defaults here
stage: prod
region: us-east-1

IAM 角色

iam 角色,即使用 Lambda 的权限代码,显示在 .yml 文件中 −

#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"

请注意,我们需要在上面的部分中提供角色的详细信息,即其他 AWS 服务所需的权限。

AWS Lambda 处理程序详细信息

handler.js 中的导出函数名称是 hello。因此,处理程序是文件的名称,后跟导出名称。

functions:
   hello:
      handler: handler.hello

此处添加的 s3 服务资源详情如下 −

# you can add CloudFormation resource templates here
#resources:
#  resources:
#    NewResource:
#      Type: AWS::S3::Bucket
#      Properties:
#        BucketName: my-new-bucket
#  Outputs:
#     NewOutput:
#       Description: "Description for the output"
#       Value: "Some output value"

使用无服务器框架部署 AWS Lambda

让我们将上述 lambda 函数部署到 AWS 控制台。您可以使用以下步骤实现此目的 −

步骤 1

首先,您必须使用以下命令 −

 sls deploy
Deploy

步骤 2

现在,您应该在 AWS 控制台中看到该函数,如图所示。无服务器 AWS 的详细信息记录在 AWS 云形成中。为此,请转到 AWS 服务并选择 CloudFormation。AWS Lambda 的详细信息显示如下 −

Cloud Framework

请注意,给出的名称是项目名称,后跟使用的阶段。

Stage Used

步骤 3

它为 AWS Lambda 创建 iam 角色,为 AWS cloudwatch 创建日志组。创建了 S3 存储桶,其中存储了代码详细信息和配置详细信息。

这是由命令 sls deploy 创建的。您无需指定 iam 角色,而是在 部署 阶段默认创建该角色。

Serverless Prod

第 4 步

云形成服务中显示了事件的详细流程。

详细流程 Hello

AWS Lambda 代码

AWS Lambda 代码及其执行设置显示在下面的屏幕截图中 −

Lambda 代码

测试 Lambda 函数时,您可以找到以下输出 −

Lambda framework Execution Framework

上述函数的日志输出显示在此处 −

Framework Output

我们还可以使用无服务器命令测试 AWS Lambda 函数,如下所示 −

sls invoke --function hello
Serverless Framework

此处显示调用命令的语法 −

slsinvoke --function hello

此调用命令触发 AWS Lambda 函数并在命令提示符中显示输出,如下所示 −

Command Trigger

您还可以在部署之前测试 Lambda 函数,并使用以下命令测试相同的命令 −

slsinvoke local --function hello

请注意,由于无法在本地环境中模拟 S3 和 DynanoDB 等资源,因此并不总是可以在本地进行测试。只能在本地测试基本函数调用。

Invoke Local

将 API 网关和 AWS Lambda 与无服务器框架结合使用

让我们看看如何创建新项目以使用 Lambda 和 api 网关。您可以使用以下命令实现此目的 −

sls create --template aws-nodejs
Api Gateway Framework

现在,在可视化代码中打开 aws-api 项目。您可以看到已创建 handler.jsserverless.yml 文件。让我们在其中进行更改以添加 api 网关。

Handler Open

您必须在 serverless.yml 中进行以下更改 −

Changes

现在,添加了使用 AWS Lambda 激活 api 网关的事件详细信息 −

Event Details

这里添加了一个名为 events 的新内容。我们已将事件指定为 http,以及其路径和方法。

路径是创建 api 网关路径时将使用的端点,使用的方法是 GET。

请注意,处理程序是 handler.hello,hello 是来自 handler.js 的导出名称。

Observe Handler

请注意,您不必在此处部署 api 网关,因为无服务器框架将执行它。

现在,我们将运行 sls deploy 命令来创建以触发器为 api 网关 的 AWS Lambda 函数。

sls deploy
Sls Deploy

请注意,部署详细信息列在上面。它提供了 Get url,其中端点作为路径详细信息。阶段是 prod,因此在 url 中使用相同的内容。函数的名称是 aws-api-prod-hello

让我们点击 url 并查看输出。您可以看到以下我们从 api-gateway get url 获得的响应 −

Response
{"message":"Go Serverless v1.0! Your function executed 
successfully!","input":{"resource":"/first-api","path":"/first-api","httpMethod":
"GET","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,
image/webp,image/apng,*/*;q=0.8","Accept-Encoding":"gzip, deflate, br","Accept-Language":"en-US,en;q=0.9","CloudFront-Forwarded-Proto":
"https","CloudFront-Is-Desktop-Viewer":"true","CloudFront-Is-Mobile-Viewer":
"false","CloudFront-Is-SmartTV-Viewer":"false","CloudFront-Is-Tablet-Viewer":
"false","CloudFront-Viewer-Country":"IN","Host":"nvbhfdojfg.execute-api.us-east-1.
amazonaws.com","upgrade-insecure-requests":"1","User-Agent":"Mozilla/5.0 
(Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)
 Chrome/66.0.3359.181 Safari/537.36","Via":"2.0 707912794802dbb4825c79b7d8626a5d.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"j70MMqkWFp6kmvuauzp_nvTbI-WwKIQmm2Jl5hzSoN6gkdvX11hh-g==",
 "X-Amzn-Trace-Id":"Root=1-5b13f9ef-5b012e36b7f40b5013a326fc","X-Forwarded-For":"157.33.133.217, 54.182.242.73","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},
 "queryStringParameters":null,"pathParameters":null,"stageVariables":null,
 "requestContext":{"resourceId":"pes5sy","resourcePath":"/first-api","httpMethod":
 "GET","extendedRequestId":"H6P9fE-MoAMFdIg=","requestTime":"03/Jun/2018:14:23:
 43 +0000","path":"/prod/first-api","accountId":"625297745038","protocol":"HTTP/1.1",
 "stage":"prod","requestTimeEpoch":1528035823928,"requestId":"b865dbd6-6739-11e8-b135
 -a30269a8ec58","identity":{"cognitoIdentityPoolId":null,"accountId":null,
 "cognitoIdentityId":null,"caller":null,"SourceIp":"157.33.133.217","accessKey":null,
 "cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,
 "userAgent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like
 Gecko) Chrome/66.0.3359.181 Safari/537.36","user":null},"apiId":"nvbhfdojfg"},"body":null,
 "isBase64Encoded":false}}

当您点击 URL 时,事件详细信息也会在输出中提供。httpMethod 为 GET,queryStringParameters 为空,因为查询字符串中没有传递任何内容。事件详细信息提供给我们在 AWS Lambda 处理程序中指定的 input

Input

我们从 api 网关获得的输出只有 body 详细信息,例如 messageinput。响应完全由 api 网关控制,以及如何将其显示为输出。

现在,让我们将输入传递给查询字符串中的 GET url 并查看显示 −

Get Url

然后您可以看到查询字符串的输出,如下所示 −

{"message":"Go Serverless v1.0! Your function executed 
successfully!","input":{"resource":"/first-api","path":"/first-api","httpMethod":
"GET","headers":{"Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,
image/webp,image/apng,*/*;q=0.8","Accept-Encoding":"gzip, deflate, 
br","Accept-Language":"en-US,en;q=0.9","CloudFront-Forwarded-Proto":"https",
"CloudFront-Is-Desktop-Viewer":"true","CloudFront-Is-Mobile-Viewer":"false",
"CloudFront-Is-SmartTV-Viewer":"false","CloudFront-Is-Tablet-Viewer":"false",
"CloudFront-Viewer-Country":"IN","Host":"nvbhfdojfg.execute-api.us-east-1.amazonaws.com",
"upgrade-insecure-requests":"1","User-Agent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64)
 AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36","Via":"2.0 
 8b1d3263c2fbd0a2c270b174d7aa3d61.cloudfront.net (CloudFront)","X-Amz-Cf-Id":"JIBZw3I-blKbnpHP8LYXPVolCgdW5KmEukZS4at9mi4vrWBMI-UKNw==",
 "X-Amzn-Trace-Id":"Root=1-5b13ff90-7d6e38d4c0e4a5d4e6184f30","X-Forwarded-For":
 "157.33.133.217, 54.182.242.127","X-Forwarded-Port":"443","X-Forwarded-Proto":"https"},"queryString
 Parameters":{"displaymessage":"Hello"},"pathParameters":null,"stageVariables":null,
 "requestContext":{"resourceId":"pes5sy","resourcePath":"/first-api","httpMethod":
 "GET","extendedRequestId":"H6TeiG34oAMFguA=","requestTime":"03/Jun/2018:14:47:44 +0000","path":"/prod/first-api","accountId":"625297745038","protocol":"HTTP/1.1",
"stage":"prod","requestTimeEpoch":1528037264252,"requestId":"12e5dca3-
673d-11e8-8966-69fcf43bd4db","identity":{"cognitoIdentityPoolId":null,"accountId":null,
"cognitoIdentityId":null,"caller":null,"exmpleIp":"157.33.133.217","accessKey":null,
"cognitoAuthenticationType":null,"cognitoAuthenticationProvider":null,"userArn":null,
"userAgent":"Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like
 Gecko) Chrome/66.0.3359.181 Safari/537.36","user":null},"apiId":"nvbhfdojfg"},"body":
 null,"isBase64Encoded":false}}

让我们将 AWS Lambda 函数更改为仅显示查询字符串详细信息,如下所示 −

'use strict';
module.exports.hello = (event, context, callback) => {
   const response = {
      statusCode: 200,
      body: JSON.stringify({
         message:(event.queryStringParameters &&     event.queryStringParameters.displaymessage!="") ? event.queryStringParameters.displaymessage : 'Go Serverless v1.0! Your function executed successfully!'
      }),
   };
   callback(null, response);
   // 如果您不使用 LAMBDA-PROXY 集成的 http 事件,请使用此代码
   // callback(null, { message: 'Go Serverless v1.0! Your function executed successfully!', event });
};

请注意,我们已根据查询字符串 display message 更改了消息。这将再次部署该函数并检查输出。它显示查询字符串变量显示消息中的详细信息,如下所示。

Display Message

现在让我们将 post 方法添加到创建的事件中,如下所示 −

Post Method

现在,部署所做的更改,您可以看到部署命令的以下输出 −

Deploy Command

请注意,直接在浏览器中测试帖子网址不会提供详细信息。您应该在 postman 中测试帖子网址。

要获取 postman,请转到 https://www.getpostman.com/apps。根据您的操作系统下载应用程序。安装后,您应该能够测试您的帖子网址,如下所示 −

Post Url

这将显示我们在 Lambda 函数中添加的消息。