Serverless计算(简称Serverless)是现在软件架构圈的热门话题。国外三大云计算提供商(亚马逊、谷歌和微软)都在这一领域投入巨资,相关书籍、开源框架、商业产品、技术会议数不胜数。什么是无服务器?它的优点/缺点是什么?我希望这篇文章能对这些问题有所启发。界面驱动应用程序(UI-drivenapplications)的一些例子我们想象一个传统的三层C/S架构,比如一个常见的电子商务应用程序(比如在线宠物店),假设服务器端使用Java,而客户端使用HTML/JavaScript:在这种架构下,客户端通常没有任何功能,系统中的大部分逻辑——认证、页面导航、搜索、交易——都在服务器端实现。将其转化为Serverless架构是这样的:这是一个大大简化的架构图,但还是有不少变化:我们去掉了原来应用中的认证逻辑,取而代之的是第三方BaaS服务。另一个BaaS的例子:我们允许客户端直接访问一部分数据库内容,这些内容完全由第三方(如AWSDynamo)托管,这里我们会使用一些安全配置来管理客户端访问相应内容的权限数据。前两点已经暗示了非常重要的第三点:之前服务端的部分逻辑已经转移到了客户端,比如维护用户会话,理解应用的UX结构(做页面导航),获取数据和渲染用户界面等。客户端实际上已经逐渐演变为单页应用程序。还有一些任务需要保留在服务器上,例如繁重的计算任务或需要访问大量数据的操作。这里以“搜索”为例。搜索功能可以从持续运行的服务器中拆分出来,以FaaS的形式实现,接收来自API网关的请求(后面会详细解释)并返回响应。此服务器端功能可以从与客户端相同的数据库中读取产品数据。我们原来的服务器端是用Java写的,而AWSLambda(假设我们使用的FaaS平台)也支持Java,那么可以稍微修改一下原来的搜索代码来实现这个搜索功能。最后,我们还可以将“购买”功能重写为另一个FaaS功能,出于安全原因,需要在服务器端而不是客户端实现。它还通过API网关公开供外部使用。消息驱动应用程序(Message-drivenapplications)再举一个后端数据处理服务的例子。假设您正在开发一个以用户为中心的应用程序,该应用程序需要快速响应的UI,并且您想要捕获和记录所有用户行为。想象一个在线广告系统。当用户点击广告时,您需要立即跳转到广告目标。同时,你需要记录这次点击,以便向广告商收费(这个例子不是虚构的,我的一个前同事最近正在做这个item重构)。传统的架构是这样的:“广告服务器”同步响应用户的点击,同时向“点击处理应用”发送消息异步更新数据库(比如从客户账户扣钱).在Serverless架构下会出现这种情况:这里两种架构的区别比我们之前的例子要小得多。我们用托管在第三方平台上的事件驱动的FaaS函数替换了长期存在的内存中任务。注意这个第三方平台提供了一个消息代理和一个FaaS执行环境,两个密切相关的系统。解构“FunctionasaService”我们多次提到FaaS的概念,现在我们来深挖一下它到底是什么意思。让我们从Amazon的Lambda产品简介开始:使用AWSLambda,您可以运行代码而无需预置或管理服务器(1)。您只需为消耗的计算时间付费——代码未运行时不收费。借助Lambda,您几乎可以为任何类型的应用程序或后端服务(2)运行代码,而无需管理。只需上传您的代码,Lambda将处理运行(3)和扩展代码以实现高可用性(4)所需的一切。您可以将代码设置为从其他AWS服务自动触发(5),或直接从任何Web或移动应用程序调用(6)。从本质上讲,FaaS是无需配置或管理您自己的服务器系统或服务器应用程序即可运行后端代码的能力,而第二项——服务器应用程序——是使其有别于当今其他一些流行架构趋势的关键因素比如集装箱。或PaaS(平台即服务)。回顾前面点击处理的例子,FaaS取代了点击处理服务器(可能运行在物理服务器或容器上,但绝对是一个独立的应用),它不需要服务器,也没有持续运行的应用。FaaS不要求代码基于特定的库或框架。从语言或环境的角度来看,FaaS是一个普通的应用。例如,AWSLambda支持JavaScript、Python和任何JVM语言(Java、Clojure、Scala等),您的FaaS功能也可以调用任何一起部署的程序,这意味着您实际上可以使用任何可以调用的语言被编译成一个Unix程序(我们稍后会谈到Apex)。FaaS也有一些不容忽视的局限性,尤其是在状态和执行时间方面,我们将在后面讨论。我们再回顾一下点击处理的例子——代码迁移到FaaS时唯一需要修改的就是main方法(startup),删除即可,可能还有一些上层消息处理(实现)的代码消息监控接口),但这很可能只是方法签名的一个小改动。所有其他代码(例如那些访问数据库的代码)都可以在FaaS中按原样使用。由于我们没有要执行的服务器应用程序,因此部署过程与传统方式有很大不同——将代码上传到FaaS平台,平台会处理其他一切。具体来说,我们要做的是上传新版本的代码(zip文件或jar包),然后调用API激活更新。横向扩展是完全自动化的、有弹性的,并由FaaS平台提供商管理。如果需要并行处理100个请求,系统自然可以支持,不需要做任何处理。FaaS的“计算容器”会在运行时按需启动执行功能,快速完成和结束。回到我们的点击处理应用程序,假设在好的一天我们的客户点击广告的次数是平时的十倍,我们的点击处理应用程序可以处理吗?我们写的代码支持并行处理吗?如果是,一个正在运行的实例可以处理这么多点击吗?如果环境允许多进程执行,我们可以自动支持还是手动配置支持?用FaaS实现你的代码需要并行执行作为一开始的默认前提,但除此之外没有其他要求,平台将完成所有可扩展性要求。FaaS中的功能通常由平台指定的一些事件触发。AWS上有S3(文件)更新、Time(定时任务)、消息总线(Kinesis)消息等,你的函数需要指定某个事件源来监听。在点击处理器示例中,我们假设已经采用了支持FaaS订阅的消息代理,如果没有,这部分也需要一些代码。大多数FaaS平台都支持HTTP请求来触发函数执行,通常以某种API网关(例如AWSAPIGateway、Webtask)的形式出现。我们在我们的宠物店示例中使用它来实现搜索和购买功能。当涉及本地(机器或运行实例)状态时,状态FaaS有一个不可忽视的限制。简单来说,你需要接受这样一个前提:函数调用中创建的任何中间状态或环境状态,都不会影响后续的任何调用。这里的状态包括内存数据和本地磁盘存储数据。从部署的角度来看,换句话说,所有的FaaS功能都是无状态的。这对应用程序架构产生了重大影响,同样,“十二要素应用程序”的概念也有完全相同的要求。在这种约束下有几种方法可以做到这一点,通常FaaS功能要么是天生无状态的——纯功能性地处理输入和输出,要么使用数据库、跨应用程序缓存(如Redis)或网络文件系统(如S3)来存储数据需要进一步处理。执行时间FaaS功能的执行时间通常是有限的。目前AWSLambda函数的执行时间不能超过五分钟,否则会被强制终止。这意味着需要调整一些长时间运行的任务才能在FaaS平台上使用。例如,您可能需要将一个原始的长时间运行的任务拆分成多个协作的FaaS函数来执行。启动延迟目前,您的FaaS功能响应请求所花费的时间可能会受到多种因素的影响,并且可能从10毫秒到2分钟不等。这听起来很糟糕,但让我们来看一个具体的情况,以AWSLambda为例。如果你的函数是用JavaScript或者Python写的,代码量不是很大(一千行以内),执行的消耗一般在10到100毫秒之间,大函数偶尔会稍微高一点。如果你的函数是在JVM上实现的,你偶尔会遇到JVM启动时间超过10秒的情况,但这只会发生在两种情况下:你的函数调用触发的频率比较低,两次调用之间的间隔超过10分钟.突发流量峰值,例如通常每秒处理10个请求的任务在10秒内激增至每秒100个请求。前一种情况可以通过hack解决:每五分钟ping一次以保持功能预热。这些问题严重吗?这取决于您的应用程序类型和流量特征。我以前的团队有一个Java异步消息处理Lambda应用程序,每天处理数亿条消息,他们根本不用担心启动延迟。如果你想写一个低延迟的交易程序,你目前肯定不会考虑FaaS架构,不管你用什么语言。不管您认为您的应用程序是否会受此影响,您都应该测试生产级负载下的实际性能。如果现在的情况不行,可以过几个月再看,因为这也是目前FaaS平台商主要着力解决的问题。API网关我们之前也遇到过一个FaaS的概念:“API网关”。APIGateway是一个配置了路由的HTTP服务器。每条路由对应一个FaaS函数。APIGateway收到请求后,会找到匹配请求的路由,调用对应的FaaS函数。通常API网关也会将请求参数转换为FaaS函数的调用参数。最后,API网关将FaaS函数执行的结果返回给请求源。AWS有自己的一套API网关,其他平台也大同小异。API网关除了单纯的路由请求外,还负责身份认证、入参验证、响应码映射等,你可能已经敏锐地意识到这是否合理。如果你有这个考虑,我们以后再说。API网关+FaaS的另一个应用场景是创建一个serverless的http前端微服务,同样具有FaaS功能的可扩展性和便捷管理的优势。目前API网关的相关工具链还不成熟。虽然这是可行的,但必须要有足够的胆量才能使用。工具链前面关于工具链不成熟的说法,指的是FaaSServerless架构平台总体情况,也有例外。Auth0Webtask非常重视提升开发者的体验。TomaszJanczuk在最新的ServerlessConf展览上做了精彩的演讲。serverless应用的监控调试还是比较棘手的,我们会在以后的文章更新中进一步探讨这方面的问题。开源无服务器FaaS的一个主要好处是只需要近透明的运行时启动调度,因此这个空间不像Docker或容器空间那样依赖于开源实现。未来肯定会有一些流行的FaaS/API网关平台实现,可以运行在私服或者开发者工作站上。IBM的OpenWhisk就是这样一种实现。不知道会不会成为大众的选择。下一次肯定会有更多的竞争者出现。除了运行时平台实现,还有很多开源工具辅助开发部署。例如,APIGateway+Lambda中的ServerlessFramework的易用性就比它的创造者AWS好很多。这是一个基于JS的如果你正在写一个JS网关应用程序,你必须了解它。另一个例子是Apex——“轻松创建、部署和管理AWSLambda函数”。Apex的一个有趣之处在于,它允许您使用AWS平台不直接支持的语言(例如Go)来实现Lambda函数。什么不是Serverless在上一篇文章中,我将“Serverless”定义为“BackendasaService”和“FunctionasaService”两个概念的结合,并详细解释了后者的特点。在我们开始讨论它的优点和缺点之前,我想多花一点时间在它的定义上,或者换句话说:区分容易与Serverless混淆的概念。我见过一些人(最近包括我自己)对此感到困惑,并认为值得澄清。与PaaS相比,ServerlessFaaS与12-Factor应用程序非常相似,它不就是PlatformasaService的另一种形式吗?就像Heroku一样?借用AdrianCockcroft的一句话很简洁:如果你的PaaS可以启动一个只运行半秒的Instances,那就叫Serverless。—AdrianCockcroft换句话说,大多数PaaS应用程序不会针对每个请求启动和关闭整个应用程序,而FaaS会。好吧,但假设我是一名熟练的12-Factor应用程序开发人员,我编写代码的方式仍然没有区别,对吗?是的,但你如何操作它是非常不同的。既然我们都是DevOps工程师,在开发阶段就会充分考虑运维,对吧?FaaS和PaaS在运维方面的关键区别在于可扩展性(Scaling)。对于大多数PaaS平台,您需要考虑如何扩展,例如您在Heroku上使用多少个Dyno实例?对于FaaS应用程序,此步骤是完全透明的。即使你配置PaaS自动伸缩,也无法细化到单个请求的级别,除非你有一个非常清晰稳定的流量曲线,可以有针对性地配置。所以FaaS应用程序在成本方面要高效得多。既然如此,为什么还要使用PaaS呢?原因有很多,最重要的因素应该是工具链的成熟度。此外,CloudFoundry可以为混合云和私有云的开发提供一致的体验。在撰写本文时,FaaS还不是一个如此成熟的平台。与NoOpsServerless相比,并不是“零运维”——虽然可能是“无系统管理员”,但这也取决于你在这条serverless的道路上走多深。“运维”的意义远不止系统管理。它还包括但不限于监控、部署、安全、网络、支持、生产环境调试和系统扩展。这些事务也存在于Serverless应用程序中,您仍然需要相应的方法来处理它们。在某些情况下,Serverless的运维难度会更高一些,毕竟它还是一个全新的技术。系统管理工作仍然完成,您只需将其外包给无服务器环境即可。这既不是坏事也不是好事——我们外包了很多内容,这取决于情况的好坏。无论哪种方式,在某个时候这种抽象级别都会崩溃,您需要来自某个地方的人工系统管理员来支持您的工作。与存储过程即服务相比,还有一种说法是将ServerlessFaaS视为“存储过程即服务(StoredProceduresasaService)”。我想原因是很多FaaS的功能演示都是以数据库访问为例。我想如果这就是它的主要用途,那么这个名字还不错,但归根结底,它只是FaaS的一个用例,以这种方式考虑FaaS会限制它的功能。我想知道无服务器最终是否会成为类似于存储过程的东西,它一开始是一个好主意,但很快就会演变成巨大的技术债务。—CamilleFournier但FaaS是否会导致类似于存储过程的问题,包括Camille提到的技术债务,仍然值得考虑。存储过程给我们的很多教训可以在FaaS场景中重新审视。存储过程的问题在于它们通常依赖于服务提供商指定的语言,或者至少依赖于指定的语言框架/扩展,因为它必须在数据库环境中执行。难以测试难以进行版本控制,或作为应用程序包进行管理尽管并非所有存储过程实现都存在这些问题,但它们很常见。看看是否适用于FaaS:第一种显然不是目前FaaS的烦恼,直接排除吧。其次,因为FaaS函数是纯代码,它们应该像任何其他代码一样容易测试。集成测试是另一个问题,我们将在稍后展开。第三,既然FaaS功能都是纯代码,版本控制自然不成问题;最近大家开始关心应用程序打包,相关的工具链也越来越成熟,比如Amazon的ServerlessApplicationModel(SAM)以及上面提到的其他Serverless框架都提供了类似的功能。2018年初,亚马逊还开通了ServerlessApplicationRepository(SAR)服务,方便组织分发应用程序和组件,也是建立在AWSServerless服务的基础上。
