浅谈 Serverless 开发和应用
AWS Serverless 服务是一种对应用工程师来说无服务器的计算方式,基础概念是将运行服务所需的基础设施交由 AWS 管理。使用 AWS Serverless 服务的工程师可以专注于面向客户逻辑服务层的开发,而不需要在基础设施的构建、管理、扩容等任务上分散过多精力。AWS Serverless 开发的核心是名为 Lambda 的计算服务。
今天我们将围绕 Lambda ,介绍在不同的应用场景下 Lambda 与各种 AWS 服务的不同组装模式,来初步探讨基于 AWS Serverless 的开发和部署。
What?
首先介绍一下什么是 Serverless 开发。
和经典的开发、编译、部署运行方式不同,使用 AWS Serverless 计算服务 Lambda,仅需要上传源文件,选择执行环境并执行,便能得到运行结果。在这过程中,服务器部署、runtime 安装、编译、都由 AWS Serverless 计算平台管理执行。对开发人员来说,只需要维护源代码和 AWS Serverless 执行环境的相关配置即可。
Why?
为什么要选择 Serverless 呢?
对开发人员来说,使用 AWS Serverless 服务能够节省大量管理基础设施架构的精力,并更好地专注于业务逻辑的开发。而对服务而言,AWS 本身的服务性质使得它能很好的支持弹性扩展和高并发场景。此外基于 AWS Serverless 的开发往往拥有快速更新、快速部署的优点,其按需收费(on-demand)的收费方式,在如轻量部署测试环境、快速验证等应用场景下对削减开支也有优势。
How?
那么,我们来看一下如何用 AWS Serverless 的相关服务迅速组装一个简单的 Web Service。
AWS Serverless 提供了丰富的服务目录,以覆盖各种功能的使用需求。搭建 Web Service 服务除了核心的计算服务 Lambda 之外,常常还需要和请求入口路由(API Gateway)、持久化存储(S3)、CDN(CloudFront)、防火墙(WAF)、域名解析(Route 53)等服务组合使用。如果需要支持 https 协议,还可以使用证书管理服务(ACM)实现。
将上述服务组装好之后,一个完整的响应请求流程将会是这样的:
用户请求经由域名解析到达 CloudFront,由 WAF 进行频率控制、IP 过滤、header 验证等安全性保障后,通过 API Gateway 路由转发给核心的 Lambda 计算服务。
Lambda 会对请求进行处理,处理时如若需要会从持久化存储 S3 中读取或存储数据,并且最终将处理结果通过 API Gateway 返回给用户端。
Lambda 在逻辑计算时产生的日志会输出到 CloudWatch 提供的日志管理服务中以便日后查询。此外,还可以进行额外的优化,比如配置 CloudFront 直接从 S3 中加载静态资源,以减轻时间和计算开销。
Lambda 的启动方式
在刚刚的 Web Service 的例子中,Lambda 的执行是由 API Gateway 服务唤起(Invoke)的。实际上 Lambda 执行可由多种方式唤起。首先 AWS 本身的服务中,常常会和 Lambda 结合使用的有消息发布(SNS)、消息队列(SQS)、负载均衡器(ALB)、状态机(Step Function)等服务。
当然通过 SDK、Command Line 或者 API 接口,也可以启动 Lambda 函数的执行。执行模式分为同步和异步两种:
同步模式的调用:需要等待 Lambda 函数执行完毕才会返回结果
异步模式的调用:在调用 Lambda 的执行接口之后会立即返回,Lambda 函数的执行结果需要通过其他途径获取。
这两种调用模式可供不同场景灵活选择使用。
消息驱动的例子
我们再看一个消息驱动的报警处理系统中使用 AWS Serverless 服务的例子。
比如我们有一个运行中的系统,设定异常报警发生时会将报警消息发送给 SNS 服务。SNS 服务是一个消息的 Pub/Sub 服务,对报警消息执行一个基础的 fan-out 发布操作,一方面通过电话、邮件通知负责人,另一方面同时调用 Lambda,Lambda 中可以进行一些对报警的自动化处理。这就是一个最简单的报警处理系统。
但是在这里要注意,SNS 服务本身不存储消息。SNS 接收到消息后,会马上进行发布消息。如果此时没有消息的接受者,那么这条消息就会被丢弃。除此之外,消息传递成功,即调用 Lambda 的接口成功之后,无论处理结果如何,消息都会被丢弃。如果 Lambda 因为一些内部逻辑错误、或者外部依赖系统故障等原因,处理过程执行失败了,那么对已经丢失的消息是无法进行重试操作的。要提高消息处理的可靠性,可以通过在 SNS 和 Lambda 之间加入消息队列服务(SQS)来实现。
SQS 标准队列提供一个无序可靠、支持高并发的队列服务,可以存储消息长达 14 天。SNS 将消息发布至 SQS,消息首先会被存储在 SQS 中。此时,再设置 SQS 为 Lambda 的事件源(event source),那么消息就会被发送至 Lambda 进行下一步处理。SQS 唤起 Lambda 可以配置为一个同步的过程,也就是说,如果 Lambda 执行失败并返回错误,SQS 就不会从队列中删除这条消息。处理失败的消息暂时会被标记为不可见,在一段隐藏期限过后,SQS 将会再次重复唤起 Lambda 来处理这条消息。这种方式可以大大提高消息处理的可靠性。
但是上述方式同时也引入了异常消息大量堆积而降低正常消息执行效率的问题。为了解决这个新问题,我们可以为消息队列配置一个 Dead-Letter Queue。如果某条消息经过多次处理依然不成功,可被从原来的队列中删除,并且转移到 Dead-Letter Queue 中。标准队列的 Dead-Letter Queue 本质上也是标准队列,同样可以继续对其中的“废弃”消息进行其他后续处理。
标准队列能够较好地支持高并发场景。一个标准队列能够同时接受大量消息,并发地唤起大量 Lambda 实例进行处理。与此对应,标准队列服务不能保证消息投递的顺序,同一条消息也可能重复投递。所以在使用 SQS 标准队列时,需要考虑消息的去重、处理逻辑的幂等性等问题。除了标准队列,SQS 还有另一种先进先出型(FIFO)队列。FIFO 牺牲了并发性能,来保证消息投递的顺序性和唯一性。在不同应用场景下,可以根据具体需求来灵活选择使用不同的队列类型。
总结
AWS Serverless 服务在解耦合、弹性扩展、跨区域部署等方面有天然的优势,但同时也有局限性:
单次 Lambda 的执行上限为 15 分钟,对长时间工作支持性较差。
构筑在 Serverless 架构上服务的可用性非常依赖于 AWS 可用性。
基于 Serverless 的开发会产生对 AWS 系统的学习成本,调试、故障处理的难度也会变高。
在实际生产活动中,需要全面考虑需求,平衡好成本与效果。在某些适合微服务的应用场景下,特别在执行短状态、临时性等任务时,基于 AWS Serverless 的开发可以成为十分便利的开发手段。
以上就是本次分享的全部内容,关于本次分享的视频,也可以点击【这里】进行查看。
作者介绍
葛馨霓,网易云信后端开发工程师,在海外有基于 AWS Serverless 的开发经验,现在从事云信后端调度开发。
版权声明: 本文为 InfoQ 作者【网易云信】的原创文章。
原文链接:【http://xie.infoq.cn/article/e5366a57a6962eafba076ec02】。文章转载请联系作者。
评论