Martin Fowler在2016.6.17号发表了一篇博客: 《Serverless Architectures》,引起业界广泛关注:
在这篇博客里,他介绍了serverless架构,以及FaaS,Microservice,Docker等流行的架构和概念,描述了Amazon AWS lambda的价值, 进一步将这种云时代的架构清晰的展现在大家的视野里。
本文很多内容来自这篇博客,让大家清晰了解Martin对serverless架构的概念和价值的阐述。 在此基础上我按照模式的讲解思路将进一步阐述我个人对Serverless架构和BaaS之间的关系,以及后续的发展。
Serverless是最新兴起的架构模式,中文意思是“无服务器”架构。跟很多其它软件类似,对Serverless还没有清晰定义,但是肯定有两个互相有重叠的定义:
1. Serverless最初是用于描述依赖第三方服务(‘云端’)实现对逻辑和状态进行管理的应用。典型的包括“富客户端”(例如单页Web应用、移动应用),
他们一般都使用基于云端的数据库(例如Parse、Firebase),认证服务(Auth0、AWS congnito)等。
这类服务以前被称为“(Mobile) backend as a Service (https://en.wikipedia.org/wiki/Mobile_backend_as_a_service)”,我将在本文中称他们为“BaaS”。
2. Serverless也可以指这样的应用,一部分服务逻辑由应用实现,但是跟传统架构不同在于,他们运行于无状态的容器中,可以由事件触发,短暂的,完全被第三方管理。
(感谢ThoughtWorks在最近Tech Radar中做出的定义)。这种思路是‘Functions as a Service / FaaS’,AWS Lambda是目前最佳的FaaS实现之一,
本文后续介绍中将使用FaaS作为这种架构的缩写。当开发Baas shaped应用,特别当开发一个富Web应用,而不是移动应用时,你会需要一些服务器端定制功能,
Faas功能也许对于这种情况是一种好的解决方案,特别是如果他们和你使用的BaaS服务集成到一定程度时,这样功能案例包括数据校验和计算敏感的处理,比如图片和视频的制作。
但是我更愿意讨论的是本领域第二种方式,相比来说技术架构更新,引领了Serverless的很多创新。然而,这两个领域开始融合,一个例子是Auth0(https://auth0.com/),一开始Auth0是作为Baas(‘Authentication as a Service’),但是随着Auth0 webtask的发布,演变成了FaaS应用。
更多场合,当开发基于BaaS的应用时,特别当开发基于web的应用而不是移动应用时,更需要一部分服务端功能。特别当跟正在使用的BaaS整合在一起时,FaaS模式可以作为最佳实践。这类功能包括数据认可(以免客户端恶意攻击)和计算敏感进程(例如图像或者视频篡改)。
在目前主流云计算IaaS和PaaS中,开发者进行业务开发时, 仍然需要关心很多和服务器相关的服务端开发, 比如缓存,消息服务, web应用服务器, 数据库, 需要对服务器进行性能优化,考虑存储和计算资源, 考虑负载和扩展,考虑服务器容灾稳定性等非业务逻辑的开发。 这些服务器的运维和开发,知识和经验极大的限制了开发者进行业务开发的效率。 如何让开发者无需在服务器实现和部署服务,而直接租用服务或者开发服务而无需关注如何在服务器中运行部署服务,对开发者来说,这是一种去服务器而直接使用服务的架构。
服务端开发在云计算时代基本是如下趋势:
Real Server->Virtual Server-> Server with Middlewares -> Service
__ 云计算的发展从IaaS,PaaS,SaaS,到最新的BaaS,在这个趋势中serverless(去服务器化)越来越明显。
IaaS将真实的物理机变成了虚拟机, PaaS进一步将虚拟机变成了包含基础设施的中间件服务。 BaaS&SaaS将中间件服务扩展到更基础的后端能力。 这些是云计算解决效率很成本的重要体现。 Serverless这种无服务器架构,用服务代替服务器,无需了解落实服务进一步提高云计算的成本和效率,从而为BaaS这种新时代云计算提供架构基础__
BaaS要被开发者广泛接受,需要在云端解决以下的限制:
要实现serverless架构, 需要利用以下技术和方案,
先讨论一个带有服务功能逻辑的传统面向客户端的三层应用,一个典型的电子商务应用(例如在线宠物商店)。
一般架构如图所示,假如服务端用Java开发完成,客户端用HTML/Javascript:
这种架构中,因为有不少系统逻辑,例如认证、页面导航、搜索、交易等在服务端完成,客户端显得相对不太智能。
采用Serverless架构,开起来如图二所示:
这仅是最简单的视图,但是即使如此,还是有不少改变。请注意并不是建议架构迁移,而是使用这个工具来解释某些Serverless概念。
1. 删除了认证逻辑,而用第三方BaaS服务取代。
2. 使用另外一个BaaS,允许客户端直接访问架构与第三方(例如AWS Dynamo)上的数据子库。通过这种方式提供给客户更安全的访问数据库模式。
3. 前两点中包含着很重要的第三点,也就是以前运行在宠物商店服务端的逻辑现在都转移到客户端中,例如跟踪用户访问,理解应用的UX架构(例如页面导航),读取数据库转化为可视视图等。客户端则慢慢转化为单页面应用。
4. 某些我们想保留在服务端的UX相关功能,例如,计算敏感或者需要访问大量数据,比如搜索这类应用。对于搜索这类需求,我们不需要运行一个专用服务,而是通过FaaS模块,通过API Gateway对http访问提供响应。 这样可以使得客户端和服务端都从同一个数据库读取相关数据。 由于原始服务使用Java开发,AWS Lambda(FaaS提供者)支持Java功能,因此可以直接从宠物商店服务端将代码直接移植到宠物商店搜索功能,而不用重写代码。
5. 最后,可以将‘purchase’功能用另外一个FaaS功能取代,因为安全原因放在服务端还不如重新在客户端重新实现,当然前端还是APIGateway。
一个不同的例子是后台数据处理服务。例如正在写一个面向用户的应用,需要对UI请求快速响应,但是同时还想获取所有发生的行为。我们设想一个在线广告系统,当用户点击一个广告时,希望快速导向目标,但是同时,需要搜集点击量以便向广告商收取费用。
传统的架构,‘Ad Server’同步地响应客户,但是同时还会向异步处理‘点击量’的应用发送一个消息更新,以便以后向广告商收费的数据库。
而Serverless架构则如下:
架构跟我们第一个例子有些许不同,这里我们用FaaS功能取代了一个一直运行的应用。此FaaS运行于方案提供商提供的消息驱动上下文之间。需要注意的是供应商提供了消息代理和FaaS,两者之间更加紧密地合作在一起。
FaaS环境通过复制出若干实例也可以并行处理这些点击,这对开发无疑带来全新概念。
FaaS可以作为最细粒度的BaaS, 就像一个接口实现可能有多个Function来完成一样。 一个BaaS服务可以有一个FaaS来实现,也可能是多个FaaS一起成一个chain来完成。 在这里我们将考虑FaaS的概念和实现。
下面的架构图来自IBM OpenWhisk, 非常贴切的描述了BaaS云代码的架构:
我们已经多次提过FaaS概念,现在我们来看看其真正含义。我们先看看Amazon Lambda产品的公开说明。我自己添加了标记,将会逐一展开说明。
AWS Lambda使得用户不需部署或者管理服务就可运行代码(1)…通过Lambda,可以虚拟化地运行任何类型应用和后台服务(2)—都是免管理的。只需上载代码,Lambda会管理其他一切(3)并且以高可用模式扩展应用(4)可以配置自动从其他AWS服务激活代码(5)或者从任何移动应用中调用。(6)
以下是FaaS,云代码实施中解决的关键问题:
FaaS功能如果使用本地状态,会有很多严格限制。简单说需要假设任何进程间或者主机状态对子进程都不可见,包括在RAM和写到本地盘上的状态。换句话说,从一个部署单元来看FaaS功能是无状态的。这一点对应用架构来说影响很大,同样‘Twelve-Factor App’概念对架构也有细致的限制。
考虑到限制,应该如何解决呢?一般来说FaaS功能要么是自然无状态,也就是提供纯功能调用,要么会使用数据库,跨进程见cache(例如Redis),或者共享文件系统(或者S3)来存放状态或者提供处理请求所需的更多输入信息。
FaaS功能一般会限制每个功能允许运行多长。目前AWS Lambda功能允许最多运行5分钟,如果超出就被强行退出。这意味着某些长时间运行的任务如果转到FaaS架构,就需要重新设计,也就是说需要多创建几个不同FaaS功能协调器,而在传统架构中,只需有一个就可以了。
目前FaaS功能多长时间会响应跟很多因素有关,其延迟可能从10ms到2分钟。听起来不太好,我们用AWS Lambda举个例子。
加入你的功能用Javascript或者Python开发,也不大(例如小于几千行代码),此时延迟一般不会超过10-100ms。更大的功能有可能会有更长的响应时间。
如果Lambda功能运行在JVM上,当JVM运行时,偶尔会看到响应时间更长(例如大于10秒)的情况,然而对于以下情况,高延迟则会很显著:
* 应用并不是很活跃,大概每十分种处理一次事件。
* 突然流量爆发。例如从每秒10次濡染增长到每秒100次。
前者一般可以通过提高响应频次的方法来解决。
这些问题需要考虑吗?的确需要看应用的具体情况。我以前团队用Java开发过一个异步消息处理Lambda应用,每天处理上亿条消息,而且没有启动延迟问题。也就是说不管采用什么开发语言,如果你想写一个低延时交易应用,现在可能并不适合采用FaaS架构。
为了确认应用是否有问题,最好是用生产类型负载测试一下。如果场景不适合,可以考虑转向FaaS提供商。
BaaS云架构中需要将一个后端服务以一个服务点(Restful API)的方式暴露给使用着,同是需要对这些服务点进行管理,提供文档,测试等信息,提高开发者体验。 当一个服务被实现后,提供一个API 网关的东西,将这个服务和服务点API关联起来。
API Gateway是一个服务器,也可以说是进入系统的唯一节点。这跟面向对象设计模式中的Facet模式很像。API Gateway封装内部系统的架构,并且提供API给各个客户端。它还可能有其他功能,如授权、监控、负载均衡、缓存、请求分片和管理、静态响应处理等。
API Gateway负责请求转发、合成和协议转换。所有来自客户端的请求都要先经过API Gateway,然后路由这些请求到对应的微服务。API Gateway将经常通过调用多个微服务来处理一个请求以及聚合多个服务的结果。它可以在web协议与内部使用的非Web友好型协议间进行转换,如 HTTP协议、WebSocket协议。
关于FaaS我们之前讨论过‘API Gateway’,一个API Gateway是一个http服务器,路由和服务点都在配置里定义,每个路由都跟一个FaaS功能有联系。当一个API Gateway接受请求,找到提供请求服务的路径,然后调用相关FaaS功能。一般API Gateway允许将http参数映射成FaaS功能需要的输入参数。API Gateway将FaaS功能结果转换为http响应,返回调用者。
Amazon Web Services等云服务提供商都各自提供自己的API Gateway。
除了API Gateway路由请求需要认证,输入验证,相应代码映射等,有时候可能还会想是否这是个好主意,那么让我们更深入论证一下。
APIGateway+FaaS的一个应用场景就是用Serverless方式创建http前端微服务,充分利用扩展,管理和其它与FaaS功能有关的其它优点。
目前API Gateway开发工具并不太成熟,因此定义API Gateway应用时候最好不是非常核心的引用。
微服务用于解决如何分解巨大单体式应用为多个服务方法解决了复杂性问题。在功能不变的情况下,应用被分解为多个可管理的分支或服务。每个服务都有一个用RPC-或者消息驱动API定义清楚的边界。微服务架构模式给采用单体式编码方式很难实现的功能提供了模块化的解决方案,由此,单个服务很容易开发、理解和维护。
对于Serverless架构里,最关键的就是用将代表复杂答题时应用的服务器消除,取而代之用一些列轻量,简单,易开发维护扩展,相互松耦合,原子性的服务来代替。 MicroService架构也是BaaS种很重要的架构模式, 我们会在后续详细介绍。
在BaaS开发架构中,服务的需要能够动态灵活按需的发布在一个轻量级无状态的容器里,这个容器就是目前流行的Docker,Docker对实施服务的DevOps提供了革命性的方案,后续会详细介绍Docker在BaaS架构体系中的重要性。
Beehive是按照BaaS架构理念构建的云开发平台, 在这个平台我们预先实现了对社交内容类开发必要的多种功能,包括数据,社交,权限,事件,计数,文件储存,地理位置等。 提供给开发者快速业务创新的平台。 目前已经有2个内部项目通过Beehive云开发平台开发。 该平台在服务器端实现了API Gateway, Data as a Service(通用数据存储)等架构特性。
下个版本,将重点实现Cloud Code(FaaS), 微服务docker化部署, 能力市场等特性。 打造云时代的新一代开发者平台。 对标Amazon APIGateway & lambda, Google FireBase, IBM BlueMix + OpenWhisk.
IBM Bluemix OpenWhisk平台让广大开发人员能够迅速构建微服务,从而可以响应诸多事件,比如鼠标点击或收到来自监视摄像头的传感器数据,执行软件代码。事件发生后,代码会自动执行。因而,开发人员不需要为预先配置基础设施之类的事情(比如服务器或系统运行)而操心――他们只需专注于代码,因而显著加快了工作流程。
Google FireBase
一开始Auth0是作为Baas(‘Authentication as a Service’),但是随着Auth0 webtask的发布,演变成了FaaS应用。
Contenful可以理解为基于BaaS基础上的一个CMS SaaS平台, 虽然是个内容管理平台,对充分体现了BaaS,Serverless, 定制化SaaS等理念。 有兴趣的同学可以深入研究下。
这是一个几乎不用服务器Serverless的内容管理系统网站架构,相比于传统使用WordPress和CraftCMS等内容管理系统可以节省网站的运营管理,相比于维护传统的LAMP架构,Serverless几乎可以没有DevOps。
有时很多客户只是需要一个静态网站,有一个漂亮的图形首页和一些其他静态页面即可,网站一旦发布,几乎很少需要运营维护。那么使用什么技术构建这种静态网站?无疑是Serverless架构,亚马逊的Web服务已经罗列出优点:
1.不需要纠结于操作系统的选择以及安全与管理
2.没有服务器需要配置 监控或扩展
3.没有成本超额造成的风险
4.没有性能考量造成的风险
目前我们定义Serverless主要意味着’Backend as a Service’ 和 ‘Functions as a Service’。针对他们我们也深入探讨了各种因素。
开始讨论有缺点之前,我们再来看看定义,或者至少定义一下什么不是‘Serverless’。很多人会很迷惘,因此讨论一下还是很值得的。
考虑到Serverless FaaS功能很像12-Factor applications(译者注:是一种创建现代,可扩展,可维护SaaS应用的方法论),它们只是像Heroku的另外一种PaaS吗?下面引用Adrian Cockcroft的一段论述:
如果你的PaaS可以将以前半秒启动的应用在20ms内启动,就叫它Serverless。——Adrian Cockcroft
换句话说,许多PaaS应用不会每次请求来了启动,请求结束则关闭。而FaaS平台是这样的。
好吧,然并卵。如果我是一个很好地12-Factor App开发者,并不会太多开发上的不同吧?这是真的。但是在运维应用上却又很大不同。因为所有好的DevOps-savvy工程师都会同时考虑开发和运维,对吧?FaaS和PaaS在运维方面最大不同来自于可扩展性(scaling)。许多PaaS架构,用户必须考虑scale,例如杜宇Heroku来说需要运行多少Dynos;而对于FaaS应用来说,这是完全透明的。即使配置PaaS应用自扩展,也不会将它设置为请求级别的(除非负载访问情况很特殊),而对FaaS应用来说,从投入角度更加有效。
考虑到这些优势,为什么还是用PaaS架构?有一些原因,但是工具,API Gateway成熟度应该是最大原因。另外,12-Factor Apps为了优化,实现PaaS时会采用App内部只读cache,而对于FaaS来说则没有这个选项。
Serverless并不意味着‘免维护’。或许根据你对Serverless有多适应,应该意味着‘不需定时维护’,有很重要的两点需要考虑。
首先,‘Ops’意味着比服务器维护更多的内容。至少还包括监控,部署,安全,网络,以及产品排错和系统扩展。这些问题对于Serverless应用来说仍然还在,需要一种策略来处理。某种程度上,在Serverless世界Ops有些困难,因为一切都是新的。
第二,即使系统管理还在发生,其实我们是他们外包给了Serverless。这并不是件坏事,我们实际上外包了很多事情。但是根据你真正想做什么,可能是件好事也可能时间坏事,有时候这种抽象会出现问题,你需要确认到底是谁在支持你的应用。
关于Serverless FaaS另外一个论点在于‘Stored Precedures as a Service’,我认为这一论点来自于很多FaaS的实现(包括本文中用到的例子)都是小段代码访问数据库。如果这就是所有要求,用FaaS当然是可以的。但是因为这仅仅是FaaS的一小部分功能,用这种想法考虑FaaS是以偏概全了。
还有人说,考虑FaaS是否会带来跟stored procedures同样的问题是值得的,包括技术方面的问题(Camile在tweet上提到这些问题)。使用stored procs值得审视FaaS上下文,这里有很多教训。例如:
经常需要用特定语言,或者是特定的框架、某种语言的扩展。
因为执行时必须要有数据库上下文,测试很困难。
版本控制需要技巧
注意,以上所述并不能涵盖所有stored procs,但是确实是我实际中遇到的问题。我们看看是否也适用于FaaS:
第一点对FaaS实施绝对不使用,因此可以毫不犹豫将它划去。
因为这里我们只讨论编码。整合测试是我们需要后续讨论的另外一个问题。
应为FaaS功能对于代码版本控制足够了,但是对于应用打包来说并没有成熟模板。Serverless框架自己提供了一套,AWS也宣称在2016年五月Serverless大会上发布一套,但是至少现在是一个值得担心的问题。
下面有一些简单公示,方便大家理解:
BaaS = 云API + 端API。
云API = service with Serverless(API Gateway + Mirocroserivce + Docker) + ...
端API= 多端SDKs + Component(前端组件)