无服务器应用模型入门

2019 年 11 月 11 日

无服务器应用模型入门

作者:薛峰


背景介绍


AWS 无服务器架构也涉及到多个 AWS 服务,如 AWS Lambda、Amazon API Gateway、Amazon DynamoDB 等。如何把这些服务资源方便地管理起来呢?今天我们介绍的 AWS 无服务器应用模型(AWS Serverless Application Model,以下简称 AWS SAM)就是一种解决方案,它是一个开源的模型,结合 AWS 自动运维相关的服务如 AWS CloudFormation 和 AWS CodePipeline,统一管理多种资源,实现我们的无服务器应用的持续集成和部署。


我们从 SAM 开始,用几个具体例子为大家介绍使用 AWS 服务实现持续集成的具体方法,帮助大家快速上手,体验其强大和便捷。


SAM 简介



松鼠 SAM 是 AWS Lamba 和无服务器应用模型的吉祥物,寓意轻便、灵活、敏捷。它头顶的头盔上是希腊字母 lambda ,代表了 AWS 无服务器核心服务 Lambda。


SAM 是 AWS 2016 年 11 月发布的一个应用架构模型。遵循开源协议,是一个开放的说明文档。通过开源协议方式发布,也体现了 AWS 推动开源流动的努力。


官方的 github 地址如下:


https://github.com/awslabs/serverless-application-model


SAM 实质上是一个 AWS CloudFormation 的扩展,基于 AWS CloudFormation 并且为无服务器做了优化,它简化了无服务器资源的管理,增加了无服务器相关的新资源类型。


SAM 模板简介


AWS CloudFormation 标准模板语法比较复杂,SAM 模板提供了一套简化的语法,我们先来看一个简单的例子:


Java


AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
GetHtmlFunction:
Type:AWS::Serverless::Function
Properties:
CodeUri: s3://sam-demo-bucket/todo_list.zip
Handler:index.gethtml
Runtime:nodejs4.3
Policies:AmazonDynamoDBReadOnlyAccess
Events:
GetHtml:
Type: Api
Properties:
Path:/{proxy+}
Method: ANY
ListTable:
Type:AWS::Serverless::SimpleTable
复制代码


最上面是模板格式的版本号和 Transform 声明。Transform 声明告诉 CloudFormation 这是一个 SAM 模板,需要转换成标准模板再执行。它的值取固定值,这里是 AWS::Serverless-2016-10-31,告诉 CloudFormation 这个模板里的声明都是无服务器应用的描述,以及进行相应的转换。


其余的两段其实都是 Resources 节点的子节点。这 2 段就是具体资源的声明:


GetHtmlFunction 段,Type: AWS::Serverless::Function,意思是创建一个 Lambda 函数,它有若干属性,如 CodeUri 指定函数的代码在 S3 的 URL,Runtime 指定运行时的语言和版本,Policies 指定它的 IAM 策略,以赋给它处理下游资源的权限。


Events 段,声明 Lambda 函数要响应的事件源。这里只有一个事件源,即创建一个 API Gateway 的 API,它有几个 API 相关的属性,比如路径、请求方式。


ListTable 这个资源 Type 是 AWS::Serverless::SimpleTable ,现在实际上是创建一个 DynamoDB 表格。这里没有额外属性,就是以默认的容量规模创建,DynamoDB 表容量默认值是每秒 5 次读写。


SAM 模板功能特性


可以和其它非 SAM CloudFormation 资源混用在同一个模板里 。SAM 模板只增加了 3 种新资源,Lambda 函数、API 和 SimpleTable,我们还可以使用其它标准 CloudFormation 资源,比如 S3 桶, Kinesis 流,Step Function 等等。


其它 CloudFormation 的标准功能 SAM 模板都支持,比如使用参数、映射和输出等,允许我们在 CloudFormation 执行时动态传入参数等, CloudFormation 的内置函数我们在 SAM 也都可以使用,如连接字符串、拆分字符串等等。ImportValue 也可使用,允许我们从现有架构中直接调取参数值,可以不再使用参数、映射等方式。总之这些标准功能使 SAM 模板可以和 CloudFormation 模板一样享受动态化的便利。


SAM 基于 CloudFormation,所以也是支持 YAML 和 JSON 两种格式。


SAM 模板特有资源类型


SAM 模板新增 3 个特有资源类型,前面的简单例子已经展示了 ,即:AWS::Serverless::Function,AWS::Serverless::Api,AWS::Serverless::SimpleTable。这是当前 Transform 版本为 AWS::Serverless-2016-10-31 所支持的特有资源类型。将来还有可能增加更多资源类型,到时请注意升级换用相应的 Transform 版本号。


第 1 个特有资源 AWS::Serverless::Function 就是声明 Lambda 函数,模板中的包括 Lambda 函数所有的属性,如 Handler、运行时、代码地址、描述等等。Events 用来声明事件源,同一函数可以支持多个事件源。 Policies 声明 IAM 策略。Environment 可以声明环境变量,可用于传递给 Lambda 函数。另外还有 Tags 声明标签,这是 AWS 管理资源的通用功能,比如用于资源分组,账单和成本分解等。


第 2 个特有资源是 AWS::Serverless::Api,用于声明 API Gateway,关于 API 的详细定义,在 DefinitionUri 指定的 swagger.yml 里。其余的属性不多,主要是:StageName 阶段名称、CacheClusterEnabled 是否启用 API Gateway 的缓存,以及 CacheClusterSize 缓存的容量。最后的 Variables 是传递给 API 的参数,比如阶段参数,也是用来灵活部署的。


第 3 个特有资源是 AWS::Serverless::SimpleTable,用于创建 DynamoDb 表。我们需要做的就是声明一下主键、类型,以及配置的容量规模。


AWS::Serverless::Function 事件源


在 SAM 模板中 AWS::Serverless::Function 资源下 Events 节点声明事件源。我们知道 AWS Lambda 是事件驱动的无服务器函数服务,所以事件源也是部署 Lambda 函数的重要属性。事件源可以有很多种,大体分为 3 类:


  • 数据状态变化,如S3对象的新增、删除。

  • 请求端点,这里主要指的是通过 API Gateway 暴露为对外服务的 HTTP API 接口。

  • 资源状态变化,如EC2实例的启动、停止等状态。


具体产生的事件源来自这些服务:S3、SNS、Kinesis、DynamoDB、Schedule、CloudWatchEvent、AlexaSkill。各事件源的各种事件及属性全部支持。具体这里不再赘述,大家可以参考各服务的事件部分相关文档。


Lambda 环境变量


Lambda 环境变量是可以动态传递给我们的函数的键值对,比如 IAM 的验证凭据,API 的密钥等等。Lambda 环境变量是 Lambda 服务本身的功能,在无服务器应用模型 SAM 里,我们可以方便地把环境变量管理起来。在 SAM 模板中以 Parameters 节点来声明环境变量。可以通过标准环境变量 API 使用,如 Node.js 的 process.env 或 Python 的 os.environ,即 Lambda 的环境变量会添加到 Node.js 的 process.env 里,方便咱们开发时使用。下面我们看一个环境变量的具体例子。


使用 SAM 模板管理 Lambda 环境变量


请先从以下 git 库下载源码。


https://github.com/xfsnow/serverless/tree/master/sam/parameters


我们打开 parameters.yaml,看下面这个片段。


Java


Parameters:
MyEnvironment:
Type: String
Default: testing
AllowedValues:
- testing
- staging
- prod
Description: Environment of this stack of resources
复制代码


这里我们声明了一个 Lambda 环境变量,变量名是 MyEnvironment。它的属性都可以顾名思义,类型是字符串,默认值是 testing,可取值是 testing、staging 和 prod。最后还有一个描述。我们建议给各种变量和资源添加描述,以清楚说明它们具体的使用情况。


Java


ApiHelloFunction:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs6.10
Environment:
Variables:
S3_BUCKET: !Ref MyEnvironment
复制代码


然后在声明 Lambda 函数时在 Variables: 段声明一个环境变量 S3_BUCKET,它的值使用 CloudFormatioin 内置函数!Ref 读取 SAM 模板中的环境变量 MyEnvironment。


Java


var bucketName = process.env.S3_BUCKET;
复制代码


相应地,在我们的 Lambda 函数代码中,index.js 中上述这段就可以通过全局变量 process.env 获取到 S3_BUCKET 这个环境变量值了。


用 CloudFormation 部署 SAM 模板


我们还使用上述 Lambda 环境变量这个例子,具体介绍一下 CloudFormation 部署的方法。


以下操作流程使用 AWS CLI 命令执行。准备环境及了解 AWS CLI 基本功能请参见 https://aws.amazon.com/cn/cli/


请先从以下 git 库下载源码。


https://github.com/xfsnow/serverless/tree/master/sam/parameters


把下面命令中的等变量值替换成你的具体的值。


在当前目录下执行以下命令,把文件上传到 S3 并打包成可用于 CloudFormation 的模板文件。


Java


aws cloudformation package \
--template-file parameters.yaml \
--s3-bucket <bucket-name> \
--output-template-file packaged_parameters.yaml
复制代码


确认已经生成 packaged_parameters.yaml 文件。


执行以下命令。–parameter-overrides MyEnvironment=prod 表示部署时为 CloudFormation 的模板参数指定值为 prod。


Java


aws cloudformation deploy \
--template-file output_parameters.yaml \
--stack-name parameters \
--capabilities CAPABILITY_IAM \
--parameter-overrides MyEnvironment=prod
复制代码


顺利地话,会看到逐渐输出的返回结果。


Java


Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - lambdaProxy
复制代码


这时到 CloudFormation 的控制台已经创建出一个 lambdaProxy,整个过程大约持续 1 到 2 分钟。 然后到 API Gateway 控制台,可以看到创建出的 lambdaProxy 的 API,点击其 Stages 下的 Prod 链接,可以看到形如下面的调用 URL: Invoke URL: https://xxxxxxxxx.execute-api.my-region.amazonaws.com/Prod


点击它,打开一个新窗口,显示


{“bucketName”:”prod”}


表示已经部署成功。


再执行一次 aws cloudformation deploy,把 MyEnvironment 参数变成 testing


Java


aws cloudformation deploy \
--template-file output_parameters.yaml \
--stack-name parameters \
--capabilities CAPABILITY_IAM \
--parameter-overrides MyEnvironment=testing
复制代码


等待执行完毕后,刷新刚才的调用 URL,可以看到内容已经更新成了


{“bucketName”:”testing”}


这个例子演示了我们在 SAM 模板中定义的环境变量在具体部署时可以灵活赋成不同的值,然后部署出相应的效果。


小结


今天我们介绍了 AWS 无服务器应用模型和 SAM 模板的基本功能和特性,并带领大家用一个实例体验了通过 CloudFormation 部署 SAM 模板。随着无服务器应用开发逐渐复杂,规模越来越大,涉及的服务和资源也会越来越多,SAM 确实为我们提供了一种使用 AWS 服务进行统一管理的方法,希望大家多多体验。


下一篇中,我们将进一步为大家讲解使用 AWS CodeBuild 构建 Lambda 函数以及使用 AWS CodePipeline 实现自动化持续集成。


作者介绍:



薛峰,亚马逊 AWS 解决方案架构师,AWS 的云计算方案架构的咨询和设计,同时致力于 AWS 云服务在国内和全球的应用和推广,在大规模并发应用架构、移动应用以及无服务器架构等方面有丰富的实践经验。在加入 AWS 之前曾长期从事互联网应用开发,先后在新浪、唯品会等公司担任架构师、技术总监等职位。对跨平台多终端的互联网应用架构和方案有深入的研究。


本文转载自 AWS 技术博客。


原文链接:


https://amazonaws-china.com/cn/blogs/china/getting-started-with-a-serverless-application-model/


2019 年 11 月 11 日 08:00347

欲了解 AWS 的更多信息,请访问【AWS 技术专区】

评论

发布
暂无评论
发现更多内容

商业计划书制作(8):财务分析部分

老壳有点爽

创业 财富自由 商业计划书 财务分析

硬件产品管理(3):产品问题整理-举例

老壳有点爽

创业 硬件产品 智能硬件

硬件产品管理(4):人体工程学验证

老壳有点爽

硬件产品 智能硬件 产品管理 人体工程学

Vim小技巧(2)

老壳有点爽

vim Linux 脚本语言

商业计划书制作(5):业务发展的历史与未来

老壳有点爽

创业 财富自由 商业计划书 业务发展的历史与未来

硬件产品管理(2):产品QA检测

老壳有点爽

硬件产品 智能硬件 QA 产品管理

编程的乐趣与苦恼

看山

随笔杂谈 人月神话

(2.6w字)网络知识点灵魂拷问——前端面试必问

执鸢者

面试 前端 网络 HTTP

商业计划书制作(2):商业计划书的完成阶段

老壳有点爽

创业 财富自由 商业计划书

商业计划书制作(4):自我评估&投资商关注重点

老壳有点爽

创业 财富自由 商业计划书

硬件产品管理(5):硬件产品工作流程管理及案例分析

老壳有点爽

创业 硬件产品 智能硬件 产品管理

Java ForEach语句判断是否为空

引花眠

bug

商业计划书制作(3):写作过程中要思考的问题

老壳有点爽

创业 财富自由 商业计划书

git回退版本,再返回最新分支git pull失败的解决经验

良知犹存

git

高并发系统三大利器之限流

java金融

架构 高并发 分布式限流 限流 单机限流

硬件产品管理(1):手板管理流程

老壳有点爽

创业 硬件产品 智能硬件 手板

Java中的单例模式(完整篇)

看山

Java 设计模式 单例模式

商业计划书制作(1):商业计划书的信息需求

老壳有点爽

创业 商业计划书 信息需求

可伸缩系统架构简介

Rayjun

分布式 可伸缩

键盘敲入 A 字母时,期间发生了什么....

小林coding

操作系统 计算机基础 键盘

什么是产品以及如何将一个开源软件项目产品化

常平

架构模式 架构设计 架构师 产品思维

程序员什么时候该考虑辞职

看山

随笔杂谈 辞职

ARTS-WEEK11

一周思进

ARTS 打卡计划

ARTS Week13

时之虫

ARTS 打卡计划

商业计划书制作(7):编写规范及常见内容

老壳有点爽

创业 财富自由 商业计划书

设计模式:建造者模式

看山

设计模式 建造者模式

如何做好项目时间管理?

石云升

项目管理 需求 项目排期

面试的时候不能做捧哏

escray

学习 面试 面试现场

高并发系统三大利器之缓存

java金融

Java 缓存 高并发 本地缓存 分布式缓存

商业计划书制作(6):商业模式

老壳有点爽

创业 商业模式 财富自由 商业计划书

《我在一线做用户增长》读书笔记及感想

王新涵

用户增长

无服务器应用模型入门-InfoQ