亚马逊AWS官方博客
新工具 – AWS SAM Local (Beta 版) – 在本地构建和测试无服务器应用程序
今天,我们将发布一款新工具 — SAM Local (Beta 版)。使用这款工具,您可以轻松在本地构建和测试无服务器应用程序。在本文中,我们将使用 SAM Local 快速构建、调试并部署一款应用程序,该应用程序允许我们通过对终端节点运行 curl 命令给 Tabs 或 Spaces 投票。AWS 去年推出了无服务器应用程序模式 (SAM),让开发人员能够更轻松地部署无服务器应用程序。如果您还不熟悉 SAM,请阅读我的同事 Orr 发布的一篇优秀文章,其中详细介绍了如何使用 SAM,读完该文章大约需要 5 分钟。SAM 的核心是基于 AWS CloudFormation 的强大开源规范,它可轻松将您的无服务器基础设施保持为代码并提供可爱的标识。
SAM Local 吸收了 SAM 的全部精华并将它们应用到您的本地计算机中。
- 它允许您使用以下命令和工具在本地开发并测试 AWS Lambda 函数:
sam local
和 Docker。 - 它允许您模拟从已知事件源 (如 Amazon Simple Storage Service (S3)、Amazon DynamoDB、Amazon Kinesis、Amazon Simple Notification Service (SNS) 等) 进行的函数调用。
- 它允许您通过 SAM 模板启动本地 Amazon API Gateway,并通过热重载对函数快速进行迭代。
- 它允许您快速验证 SAM 模板,甚至将该验证与 Linter 或 IDE 集成
- 它为您的 Lambda 函数提供交互调试支持
有多种安装 SAM Local 的方法,但最简便的方法是通过 NPM。通过运行 npm install -g aws-sam-local
命令可以快速安装,但如果您希望获得最新版本,始终可以直接从来源安装: go get github.com/awslabs/aws-sam-local
(这将创建一个名为 aws-sam-local 而非 sam 的二进制文件)。
我想要投票,因此我们来编写一款简单的 SAM 应用程序,将票投给 Spaces 而不是 Tabs。我们将使用非常简单但功能强大的 API Gateway 架构来处理 Lambda 函数,并将结果存储在 DynamoDB 中。最终,用户应能够对 API 运行 curl 命令 curl https://SOMEURL/ -d '{"vote": "spaces"}'
并返回票数。
我们首先来编写一个简单的 SAM template.yaml:
AWSTemplateFormatVersion : '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
VotesTable:
Type: "AWS::Serverless::SimpleTable"
VoteSpacesTabs:
Type: "AWS::Serverless::Function"
Properties:
Runtime: python3.6
Handler: lambda_function.lambda_handler
Policies: AmazonDynamoDBFullAccess
Environment:
Variables:
TABLE_NAME: !Ref VotesTable
Events:
Vote:
Type: Api
Properties:
Path: /
Method: post
我们创建一个 [dynamo_i] 表,并通过一个环境变量向我们的 Lambda 函数公开该表,该环境变量名为 TABLE_NAME
。
为了测试此模板是否有效,我继续调用 sam validate
确保我没有打错字。该命令返回 Valid!
,接下来我们继续处理 Lambda 函数。
import os
import os
import json
import boto3
votes_table = boto3.resource('dynamodb').Table(os.getenv('TABLE_NAME'))
def lambda_handler(event, context):
print(event)
if event['httpMethod'] == 'GET':
resp = votes_table.scan()
return {'body': json.dumps({item['id']: int(item['votes']) for item in resp['Items']})}
elif event['httpMethod'] == 'POST':
try:
body = json.loads(event['body'])
except:
return {'statusCode': 400, 'body': 'malformed json input'}
if 'vote' not in body:
return {'statusCode': 400, 'body': 'missing vote in request body'}
if body['vote'] not in ['spaces', 'tabs']:
return {'statusCode': 400, 'body': 'vote value must be "spaces" or "tabs"'}
resp = votes_table.update_item(
Key={'id': body['vote']},
UpdateExpression='ADD votes :incr',
ExpressionAttributeValues={':incr': 1},
ReturnValues='ALL_NEW'
)
return {'body': "{} now has {} votes".format(body['vote'], resp['Attributes']['votes'])}
我们在本地测试一下这个函数。我需要创建一个真实的 DynamoDB 数据库进行演示,并且需要通过环境变量 TABLE_NAME
提供该数据库的名称。我可以使用 env.json
文件来执行该操作,也可以直接在命令行中传递它。首先,我可以通过调用
$ echo '{"httpMethod": "POST", "body": "{\"vote\": \"spaces\"}"}' |\
TABLE_NAME="vote-spaces-tabs" sam local invoke "VoteSpacesTabs"
来测试 Lambda 函数,它返回 Spaces 的票数,因此从理论上讲,函数内容全都正确无误。用键盘输入上述全部内容比较费劲,但我可以使用 sam local generate-event api
生成示例事件,并将该事件传递到本地调用。最简单的方式是在本地运行我们的 API。让我们运行: sam local start-api
。接下来,我可以对我的本地终端节点运行 curl 命令进行测试。
我将运行命令 $ curl -d '{"vote": "tabs"}' http://127.0.0.1:3000/
,该命令返回:“tabs now has 12 votes”。当然,第一次尝试编写此函数的效果并不完美。我编辑并保存了几次。热重载的其中一个优点是我可以随意更改函数,而不必执行任何额外的操作来测试新函数。这大大简化了迭代开发。
假设我们不希望通过网络访问真正的 DynamoDB 数据库。我们应该怎么做?我们可以下载 DynamoDB Local,并通过运行如下命令启动它: java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar -sharedDb
。然后,我们可以在 Lambda 函数中使用 AWS_SAM_LOCAL
环境变量,以决定其行为方式。我们来稍微修改一下函数:
import os
import json
import boto3
if os.getenv("AWS_SAM_LOCAL"):
votes_table = boto3.resource(
'dynamodb',
endpoint_url="http://docker.for.mac.localhost:8000/"
).Table("spaces-tabs-votes")
else:
votes_table = boto3.resource('dynamodb').Table(os.getenv('TABLE_NAME'))
这样,我们就使用本地终端节点连接到本地数据库,这让在没有 WiFi 的环境下工作变得更轻松。
SAM Local 还支持交互调试!在 Java 和 Node.js 中,我只需传递 -d
标记和一个端口,即可立即启用调试程序。在 Python 中,我可以使用诸如 import epdb; epdb.serve()
之类的库并通过库进行连接。然后,我们可以调用 sam local invoke -d 8080 "VoteSpacesTabs"
,我们的函数将暂停执行,等待您逐步完成调试程序。
好的,我想我们已经准备就绪,现在开始部署吧!
首先,我将调用 sam package
命令 (该命令只是 aws cloudformation package
的别名),然后我将使用该命令的结果来运行 sam deploy
命令。
$ sam package --template-file template.yaml --s3-bucket MYAWESOMEBUCKET --output-template-file package.yaml
Uploading to 144e47a4a08f8338faae894afe7563c3 90570 / 90570.0 (100.00%)
Successfully packaged artifacts and wrote output template to file package.yaml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file package.yaml --stack-name
$ sam deploy --template-file package.yaml --stack-name VoteForSpaces --capabilities CAPABILITY_IAM
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - VoteForSpaces
这将转到我们的 API:
我将跳到生产阶段,并添加一些速率限制,以防你们过度投票,但另一方面,我们已经完成了本地工作并将它部署到云中,而这并不复杂。我非常享受第一次部署就成功的状态!
现在,您可以投票并实时查看结果了!http://spaces-or-tabs.s3-website-us-east-1.amazonaws.com/
我们希望 SAM Local 能够简化无服务器应用的测试、调试和部署。我们提供了 CONTRIBUTING.md 指南,并欢迎你们提交提取请求。请 @ 我们,让我们知道您构建的超酷应用程序。您可以查看我们的新增功能文章以及此处在线提供的文档。
– Randall