Serverless架构指的是使用了第三方的“后端作为服务”(BaaS),以及/或包括了在“函数作为服务”(FaaS)平台上,有管理的临时容器中运行自定义代码的应用设计。基于这种思想,相关的比如单页应用就可以使用此架构,从而移除传统的,永远部署在服务器上的组件。Serverless架构可以显著减少运行成本,复杂度以及工程时间,代价是提高了对提供商相对不够成熟服务的依赖。
Serverless计算,简称Serverless,是软件架构世界的一项热门主题。云服务三巨头——Amazon,Google和Microsoft——都大量投入在了Serverless上,这带来了一堆书目,开源项目和会议,而软件厂商也致力于这一主题。但是什么才是Serverless,为什么它值得(或不值得)研究?我希望这篇文章能够在这些问题的解答上给你带来稍许灵感。
首先,我们来看看Serverless“是什么”。稍后再来谈谈它的优势和弱点。
什么是Serverless
和众多软件趋势相仿,Serverless的真面目并没有十分清晰的解释。它首先会引入两个不同却相交的领域:
- Serverless最初被用作描述大量或全面依赖第三方云服务来管理服务端逻辑和状态的应用。这些就是典型的“重客户端”应用,比如单页网页应用,或者手机应用——都使用了广阔的云数据库生态(比如Parse和Firebase),验证服务(比如Auth0,AWS Cognito)等等。这些服务早先被称为“(移动)后端作为服务”,后面的文章会使用缩写“BaaS”来代表。
- Serverless也可以还是让应用开发者来写服务端逻辑,但是与传统架构迥异的是,它是运行在无状态计算容器中的,由事件触发,短暂(可能仅在调用时存在),而且完完全全交由第三方管理。你可以将其当作“函数作为服务”或者“FaaS”(注意:这个名字的原始来源是@marak发的一个推特,现在已不对公共开放)。AWS Lambda是当前最为流行的FaaS平台实现之一,不过其他类似产品也有很多。
本文的主要关注点会集中在FaaS上,不仅因为它作为Serverless领域的一部分,后者更新鲜而且吸引了不少热度,还因为它与我们脑海里的典型技术架构有着显著的差别。
BaaS和FaaS在其运行属性上保持着关联(比如资源管理),而且经常放在一起使用。大型云服务提供商都有着涵盖BaaS和FaaS在内的“Serverless系列产品”。Google的Firebase BaaS数据库显式地依赖了Google Cloud Functions对Firebase提供的FaaS支持。
小公司在这两个领域也存在相似的连接关系。Auth0依托于一个实现了用户管理等多个层面的BaaS产品,还接连创建了FaaS服务Webtask。该公司在Extend上将此思想进一步深化,此产品能使其他SaaS和BaaS企业轻而易举地为已有产品增加FaaS能力,从而创建出统一的Serverless产品。
几个例子
UI驱动的应用
来考虑一个传统的三层结构,面向用户且包含服务端逻辑的系统。电商应用就是一个不错的例子——不妨就用在线宠物商店来表示。
传统上,该应用的架构会如下图所示。假设服务端使用Java或者Javascript实现,客户端使用HTML和Javascript组件实现:
使用这种架构的话,客户端就显得相对不那么机灵,系统中存在的验证逻辑,页面导航逻辑,搜索,交易等——都在服务端应用里面。
而使用Serverless架构的话,应用最后则会像这样子:
这是个被大大简化了的视图,不过我们还是能看到不少显著的改变:
- 删除了原有应用的验证逻辑,使用第三方的BaaS服务(比如Auth0)替代。
- 使用了其他BaaS。客户端可以直接访问数据库的子集(产品列表),而数据库自身则由第三方提供(比如Google Firebase)。客户端访问数据库时很可能会有不同的安全档案,而不是在服务端使用资源访问数据库。
- 前两点可以引出非常重要的三代点:宠物商店的部分逻辑移交到了客户端——比如追踪用户session,理解应用到UX结构,读数据库并进行可视数据转换等等。客户端就变成了一个单页应用。
- 我们可能会在服务端保留一些UX相关的功能,比如,计算密集的活着需要访问大量数据的功能。在宠物商店的例子中,这种功能就是“搜索”。我们可以通过API网关(后面会提到)来使用一个能够响应HTTP请求的FaaS函数,而不是把搜索功能放在持续运行的服务之上。客户端和服务端的搜索都会从同一个数据库中读取数据。如果我们使用AWS Lambda作为FaaS平台,我们就能在不重写代码的情况下将搜索逻辑移动到宠物商店云函数上,因为Lambda也支持Java和Javascript——应用的原始实现语言。
- 最后,我们把“支付”功能替换成了另一个独立的FaaS函数。处于安全考量,这个函数的使用放在了服务端而不是直接在客户端重新实现。该功能也交由API网关处理。将不同逻辑需求分割成单独部署的不同组件在FaaS的使用过程中是很常见的。
退一步来看,这个例子还展示了Serverless架构的另一个十分重要的特点,在原始的版本中,所有的流程,控制和安全都被中央服务应用所管理,而在Serverless的版本中则没有特定的中央角色。我们使用了编排的方式,每一个组件都扮演了架构感知者——这一思想也常见于微服务中。
使用此方法的好处有很多。Sam Newman在Building Microservice一书中写道,使用这种方式构建的应用经常“更灵活更好变化”,在全局和部分组件的更新中都是如此。系统有了更好的关注点分离,也有了更好的成本效益,Gojko Adzic曾谈及这一点。
当然,这样的设计也是有所取舍的:它需求更好的分布式监控(后面会提到),而对依赖平台的安全性也显著加强。更基础地来看,我们手上有了一堆可以调整的组件而不是之前的单体应用。它带来的灵活性和成本是否能抵消随之而来的多个后端组件的复杂性需要视情况而定。
