近期灵雀云技术专家邵明岐翻译了 Mike Roberts & John Chapin 所著的《What is Serverless》一书的部分内容,可以说是对 Serverless 科普与观察的上佳素材。
在了解了何为 Serverless,各种服务组件之后,如何将服务组件组合成完整的应用程序?基于 Serverless 开发的应用架构什么样子?与传统非 Serverless 应用程序架构相比,Serverless 有哪些优势?本文将回答这些问题。
假设有这么一个应用程序,它是一个支持多用户的手机游戏,具有以下高级要求:
友好的移动端交互界面;
具备用户管理和身份验证;
有一些基本的业务逻辑,比如游戏排行榜,历史记录等。
我们暂时忽略游戏中可能会遇到的其他功能,毕竟我们的目的不是实际开发一个游戏,而是将 Serverless 程序架构与传统的非 serverless 架构进行比较。
根据上面的要求,传统非 Serverless 架构看起来应该是这样的:
Native Mobile App 是 iOS 或者安卓客户端。
Java Application Server 是 Java 代码编写的应用逻辑,运行在 Tomcat 或者 JBoss 这类应用服务器里面。
数据存储在关系型数据库,比如 MySQL 里面。
在这个架构中,移动应用程序负责呈现游戏界面并处理来自用户的输入,但它将大多数实际逻辑删除到后端,从代码的角度来看,移动应用程序简单轻便,它使用 HTTP 调用后端 Java 应用程序提供的不同 API。
用户管理、身份验证和各种游戏操作都使用 Java 应用程序代码进行封装, 后端应用程序还与单个关系数据库交互,以便维护正在进行的游戏的状态,并存储已完成游戏的结果。
这个简单的架构似乎符合我们的要求,那么为什么对它做改进呢?关键在于未来开发和运维方面带来的一系列潜在的挑战和陷阱。
在构建游戏时,需要具备 iOS 和 Java 开发方面的专业知识,以及配置,部署和操作 Java 应用程序服务器的专业知识,还需要配置和操作关系数据库服务器。除了应用服务器和数据库,也需要配置和运行各自的主机,无论这些系统是基于容器还是直接在虚拟或物理硬件上运行。我们还需要通过配置路由策略,访问控制列表等,来确保系统组件之间以及用户端和服务端之间的网络连通性。
有了上面这些,我们仍然只是提供最基本的让游戏可用的环境还没有涉及安全性、可扩展性或高可用性,这些都是现代生产系统的关键方面。最重要的是,即使在简单的体系结构中,也存在许多固有的复杂性,用来满足现实世界各种各样的需求。构建系统并不难,但是当我们修复错误,添加功能或尝试快速构建新的创新想法时,所有这些复杂性将会变成强大的阻力。
现在已经发现了传统架构的一些挑战,如何改变它?让我们看看如何能够满足高级需求,并使用 Serverless 架构模式和组件来解决传统方法的一些挑战。
在之前的文章已经说过了,Serverless 组件可以分为两类,BaaS 和 FaaS。考虑到游戏的要求,其中一些可以通过 BaaS 组件解决,一些可以通过 FaaS 组件解决。
基于 Serverless 构建的游戏,架构看起来应该是下图这个样子的:
虽然用户界面仍是移动应用程序的一部分,需要自己通过代码来实现,但用户身份验证和管理可由 AWS Cognito 等 BaaS 服务处理,这些服务可以直接从移动应用程序调用,以处理注册和身份验证等面向用户的功能,其他后端组件可以使用相同的 BaaS 来检索用户信息。
现在由 BaaS 处理用户管理和身份验证,后端 Java 应用程序的逻辑被简化了, 可以使用另一个组件 AWS API Gateway,以安全、可扩展的方式来处理移动应用程序和后端游戏逻辑之间的 HTTP 请求。然后可以将每个不同功能的操作封装在 FaaS 函数中。
这些后端 FaaS 功能可以与像 DynamoDB 这样的 NoSQL 数据库进行交互,以存储游戏的状态。实际上,一个重大变化是不再在服务器端应用程序代码中存储任何会话状态,而是将所有会话状态保存到 NoSQL 存储中。虽然这可能看起来很麻烦,但它有助于扩展。
移动应用程序可以无缝访问同一个数据库,以检索过去的结果和排行榜数据。这允许我们将一些业务逻辑移动到客户端实现,而不是将其放到到后端实现。
这种新的 Serverless 架构看起来很复杂,而且它比传统架构需要更多的组件,但是,由于我们使用完全托管的 Serverless 组件,已经消灭了很多因为管理应用程序基础设施和底层系统而带来的挑战。
我们编写的代码现在几乎完全集中在游戏独特的业务逻辑上,更重要的是,组件已经解耦和分离,因此,可以非常快速地将它们切换出来或添加新逻辑,而不会出现非无服务器架构中固有的阻力。
扩展,高可用性和安全性也有所提升,这意味着随着我们的游戏越来越流行,不需要担心购买功能更强大的服务器,也不需要担心数据库是否会崩溃,或者排查防火墙配置故障。
简而言之,我们降低了制作游戏的人工成本,以及运行游戏的风险和计算成本,它的所有组成部分都将灵活扩展。当我们有一些新的想法,交付期会大大缩短,可以开始获得反馈并更快迭代。
云计算的基础设施外包带来五大好处:降低人工成本、降低风险、降低基础设施成本、扩展性、交付时间 。Serverless 同样也有这五大优点, 前四个都或多或少是关于成本节约的,这就是 Serverless 更为人所知的:如何以更低的成本做以前做过的同样的事情。但是,对我们来说,节省成本并不是无服务器最令人兴奋的部分,较大的好处是,它减少了从新的想法到实施上线的时间,换句话说,它能够让你更快地创新。
我们在之前说过,Serverless 本质上不再需要关心自己的服务器和进程 ,只需要关心应用程序的业务逻辑和状态,所有其他不必要的工作都交给平台来处理。这里的第一个明显好处是运维工作量减少, 您不再管理操作系统,补丁级别,数据库版本升级等。如果您正在使用 BaaS 数据库,消息总线或对象存储,那么祝贺你,这些基础架构也都不要你来运维。
通过其他 BaaS 服务,对于节省人工成本是比较直观的,自己开发的逻辑更少了。我们已经多次讨论过身份验证的 BaaS 服务,其中较大的好处是可以使用较少的代码来定义开发、测试、部署和运营,所有这些都减少了工程师时间成本,另一个例子是像 Mailgun 这样的第三方邮件 BaaS 服务,它消除了处理电子邮件发送和接收的大部分复杂工作。
与传统方法相比,FaaS 还具有显著的劳动力成本优势。使用 FaaS 进行软件开发得以简化,因为大部分基础架构代码已移至平台。这里的一个例子是 HTTP API 服务的开发,这里所有的 HTTP 级请求和响应处理都是由 API 网关完成的。
使用 FaaS 进行部署更容易,因为我们只是上传打包成 Zip 格式 (如果是 JS 或者 Python 脚本语言) 的基本代码,或者如果是 Java 的话,则上传普通的 JAR 文件,没有要管理的 Puppet,Chef,Ansible 或 Docker 配置。其他类型的操作活动也变得更加简单,例如,由于不再关注“永远在线”服务器进程,因此可以将监控限制为更多面向应用程序的指标。这些是统计信息,例如执行持续时间和面向客户的指标,而不是可用磁盘空间或 CPU 使用率。
当考虑软件应用风险时,我们经常考虑对故障和宕机的敏感程度,我们的团队负责管理的不同类型的系统或组件的数量越多,发生问题的风险就越大。我们可以不是自己管理这些系统,而是像之前描述的那样,让“外包”系统来解决这些问题。
虽然整体而言仍然面临应用程序发生故障的风险,但我们选择以不同的方式管理风险 -- 我们现在依靠其他人的专业知识来解决其中的一些故障,而不是自己修复它们。这通常来说是一个好主意,因为应用的技术栈中,一些技术是平时很少发生变更的,当它们发生故障时,修复时间和难度都不确定。通过 Serverless,我们可以显著减少直接操作的技术栈数量,那些我们仍在自己管理的技术,通常是我们非常熟悉并且频繁变更的,因此我们更有能力在失败时自信地处理失败。
例如,管理分布式 NoSQL 数据库。一旦安装了组件,节点发生中的故障可能相对罕见,但是当它发生故障时,会发生什么?您的团队是否具备快速有效地诊断,修复和恢复问题的专业知识?常常没有。相反,团队可以选择使用 Serverless 的 NoSQL 数据库服务,例如 Amazon DynamoDB, 虽然 DynamoDB 中的中断偶尔会发生,但由于亚马逊拥有致力于此特定服务的整个团队,因此它们发生故障的次数更少,并且能够更快的恢复。
因此,我们说当使用 Serverless 技术时,风险会降低,因为组件的预期宕机时间会减少,并且修复它们的时间会更少。
通常,当运行应用程序时,我们必须弄清楚它们将运行的底层主机类型和数量。例如,数据库服务器需要多少内存和 CPU?需要多少个不同的实例来支持扩展?或者如何支持高可用性(HA)?
一旦规划了我们需要的主机或资源,就可以分配应用程序的哪些部分将在哪些资源上运行。最后,一旦我们开始准备部署应用程序,就需要实际获得我们想要的主机,这是环境配置。
整个环境配置过程很复杂,我们很少提前知道我们的资源要求是什么,因此高估了我们的计划,这称为过度配置,这实际上是正确的做法:拥有备用容量并保持应用程序运行比在负载下降低更好。对于某些类型的组件(如数据库),可能很难在以后扩展,因此可能希望通过过度配置,来承载未来预期的负载。
过度供应意味着我们总是为满足处理峰值预期负载所需的容量付费,即使我们的应用程序没有遇到负载也是如此。最极端的情况是,我们的应用程序处于空闲状态时,我们正在为服务器付费,而事实上它并没有做任何有用的事情。但即使我们的应用程序处于活动状态,我们也不希望主机得到充分利用。相反,我们希望留下一些空间,以应对意外的负载峰值。
无服务器给这个领域带来的巨大好处是不需要计划,分配或配置资源,让服务较精确地提供我们在任何时间点所需的容量,如果我们没有任何负载,那么不需要任何计算资源,也不会支付任何费用。如果我们只有 1 GB 的数据,我们不需要容量来存储 100 GB。我们相信当需要时,服务将按需扩展,并且这同样适用于 FaaS 和 BaaS 服务。
除了消除资源分配带来的问题,无服务器还使成本更加高效。对于负载不一样的各种应用程序,我们将通过使用无服务器来节省资源成本。例如,如果我们的应用程序每小时只运行 5 分钟,我们只需支付每小时 5 分钟,而不是整个 60 分钟。此外,良好的无服务器产品将具有非常较精确的使用增量 ; 例如,AWS Lambda 按 100 毫秒的使用时间收费,比 EC2 的每小时计费较精确 36,000 倍。
在现代非 Serverless 应用程序中,我们通过自动伸缩等技术获得了一些收益,但是,这些方法通常不如无服务器产品那么较精确,并且通常无法自动扩展数据库。
所有这些资源成本优势都来自于这样一个事实,即 Serverless 服务可以较精确地满足我们的需求。那么如何才能真正实现这种扩展呢?我们需要设置自动缩放组吗?监控流程?没有!事实上,缩放是自动完成的,不费力气。
以 AWS Lambda 为例。当平台收到第一个触发函数事件时,它会启动一个容器来运行代码,如果在收到另一个事件时仍在处理此事件,则平台将启动代码的第二个实例以处理第二个事件。这种自动、零管理、水平扩展将持续到 Lambda 有足够的代码实例来处理负载。
一个特别好的方面是 AWS 仍然只会根据你代码执行的时间收取费用,无论它有多少个容器要启动。例如,假设所有事件的总执行时间相同,在一个容器中按顺序调用 Lambda 100 的成本与在 100 个不同容器中同时调用 Lambda 100 次的成本完全相同。
通过采用 Serverless 技术,可以带来显著的成本节剩
康卡斯特有线电视公司首席技术官 Sree Kotay 在 2016 年 8 月 AWS 峰会上说:他不是在谈论 Serverless,他在谈论康卡斯特如何从各种其他基础设施外包中获益匪浅,从“本地”转向云计算:
经历了云和敏捷的这一旅程,过去五年我们已经实现了收益,而且这些收益都是围绕成本和规模进行的,它们是关键且重要的,但有趣的是它们并不是最引人注目的,最关键部分是这真的改变了你的创新周期,它从根本上改变了你对产品开发的看法。
——Sot Kotay
我们要提出的一点是,一家大公司的首席技术官说,成本和规模对他来说并不是最重要的,最重要的是创新。那么 Serverless 如何在这方面提供帮助呢?
Adrian Cockcroft(AWS 云架构战略副总裁,Netflix 前云架构师)谈到:
我们开始看到开发应用程序的时间越来越短,小型开发团队在短短几天内从头开始构建生产就绪的应用程序。他们使用简短的功能和事件将强大的 API 驱动的数据存储和服务粘合在一起。已完成的应用程序已具有高可用性和可扩展性,高利用率,低成本和快速部署。
在过去几年中,我们看到通过持续交付和自动化测试以及 Docker 等技术改进开发的增量周期时间取得了很大进展。这些技术很棒,但只有在设置和稳定后才能实现。对于真正蓬勃发展的创新而言,缩短周期时间是不够的,您还需要更短的交付周期 -- 从新产品或功能的概念化到以最小的可行方式部署到生产环境的时间。
由于 Serverless 消除了在生产中大规模构建,部署和运行应用程序的大量附带复杂性,因此它为我们提供了巨大的杠杆作用,以至于软件交付方式可以颠倒过来。通过正确的组织支持,创新和“精益创业”风格,实验可以成为所有企业的默认工作方式,而不仅仅是为初创公司或“黑客日”保留的东西。
这不仅仅是一种理论。除了 Adrian 的的观点之外,我们看到相对缺乏经验的工程师完成项目通常需要几个月的时间,并需要更多资深工程师的帮助。相反,使用 Serverless,他们能够在几天内基本上无需帮助地实施项目。
这就是为什么对 Serverless 感到非常兴奋:除了节省所有成本之外,还可以释放他们的能力,让他们专注于让产品与众不同的地方。