Serverless并不神秘,用一个简单的例子就可以说明。我们设计了一个AI应用程序,可以识别图片中的人的种族。我们将其设置为公共云上的SaaS服务并提供给客户。典型的后端架构设计如下:在这个架构中,我们购买的云主机运行TomcatWebServer来托管用Java编写的AI应用程序。用户通过API上传图片。受限于云主机本地存储空间,为满足大量客户同时上传图片,AI应用实现存储网关将图片导入公有云对象存储。图片导入后,AI应用从对象存储中读取图片进行识别,并将结果存储在公有云数据库(如RDS)中,用户通过API查询结果。AI应用上线一段时间后受到了用户的欢迎,越来越多的企业开始使用该服务。据统计,大部分公司在上午9:00-11:00和下午2:00-5:00之间集中上传图片。动态创建更多云主机来响应客户。AI应用的架构演变为:在这个架构中,我们需要做以下事情:管理云主机。我们需要关心系统级的配置,比如CPU数量、内存大小、IP地址等等。同时,还需要关心云主机的操作系统,制定部署AI应用的策略。操作系统和Tomcat的安全补丁不容忽视,否则竞争对手可能会雇佣黑客来攻击我们的系统。配置公有云的Auto-Scaling策略,应对高峰时段的突发流量。使用公共云的对象存储和数据库。编写AI应用程序。要完成这些任务,我们不仅要开发AI应用,还要运营配套业务(比如管理云主机和操作系统的生命周期)。这就是当前结构的现实:80%的配套业务为20%的核心业务。接下来使用serverless架构重写AI应用:启动多个运行AI应用代码的进程,并发处理用户上传的图片。在serverless架构的AI应用中,我们只需要做两件事:使用公有云的对象存储和数据库。使用公有云的无服务器框架编写AI应用程序。相比之前的架构,我们不再操作云主机、操作系统、Tomcat,也不需要配置Auto-ScalingGroup。每一张图片上传后,公有云的Serverless框架都会启动一个进程运行AI应用,自动实现横向扩展。我们最终只需要关心核心业务。AI应用使用Serverless框架支持的语言编写(例如AWSLambda支持Java、Python、JVM等语言),非核心业务全部外包给公有云运营商。我们的无服务器AI应用程序使用两种技术。首先,使用公有云提供的对象存储和数据库服务,统称为BaaS(BackendasaService,后端即服务)。其次,使用了Lambda框架,称为FaaS(FunctionsasaService,功能即服务)。使用BaaS和FaaS是Serverless应用的基本特征,满足这两个基本特征的应用就可以称为Serverless应用。是BaaS,不是PaaSAI应用使用对象存储和数据库,未来还可能使用消息队列。直观的感觉就是我们在用PaaS,为什么要创造一个新词BaaS呢?技术圈里有太多容易混淆的名词。BaaS不是PaaS。它们的区别在于PaaS需要参与应用的生命周期管理,而BaaS只提供应用所依赖的第三方服务。一个典型的PaaS平台需要为开发者提供部署和配置应用程序的手段,比如自动将应用程序部署到Tomcat容器中,管理应用程序的生命周期等。BaaS不包含这些内容。BaaS只是以API的形式提供应用所依赖的后端服务,如数据库、对象存储等。BaaS可以由公共云服务提供商或第三方供应商提供。比如被Facebook收购的Parse就是知名的MBaaS(MobileBackendasaService)提供商。从功能上来说,BaaS可以看作是PaaS的一个子集,即提供第三方依赖组件的部分。FaaS是Serverless的核心。AI应用最初是一个典型的Java程序,可能会用到Spring等技术,因为我们需要一个框架来保证程序的各个组件能够被正确加载,需要MVC来保证RESTAPI由正确的控制器。AI应用部署在Tomcat容器中,运行在云主机上,24/7全天候运行。我们提供不间断的服务。晚上12点到早上8点,几乎没有用户使用,但我们还是要让它留着,防止偶尔深夜使用的用户出现503错误和误会AI服务不稳定。我们买的云主机是付费的,虽然有一半时间CPU使用率几乎为0,但是没有公有云是按CPU使用率计费的,你不工作的时间是要付费的。我们必须关注Auto-ScalingGroup的配置。如何准确配置Auto-Scaling策略是一项技术活,需要长期积累经验。在早期,我们不得不部署更多的闲置云主机,以保证服务不会受到Auto-Scaling的影响。由于配置不当造成的拥塞。用serverless架构重写AI应用后,这些痛苦都烟消云散了。删除了Spring框架和Tomcat。使用Lambda的JavaSDK,你只需要实现一个FunctionHandler来处理图片上传完成事件,就像写一个Callback一样简单。在FunctionHandler中调用图像识别的相关逻辑,然后调用数据库的RESTAPI存储结果。不需要搭建MVC,不需要配置TomcatXML文件,我们完全去掉了存储网关的功能,因为用户可以直接上传图片到对象存储。AI应用程序不必24/7全天候运行,它只是在没有用户上传图片时的编译代码。当用户图片上传完成后,FaaS会为AI应用启动一个新的进程来执行代码。代码执行完成后进程自动销毁。我们只需要为这几十秒的代码执行买单,省了很多钱。最后,我们不用担心Auto-Scaling,FaaS会在需要的时候自动扩容。这些就是FaaS的核心,从上面的例子可以总结出它的特点:FaaS运行的是后端代码,而不是整个后端程序。比如AI应用只包含图片上传完成事件的处理逻辑,并不是一个完整的后台程序,而是一段后台代码。代码是通过事件触发的。由于不再有等待或轮询用户请求的长时间运行的进程,代码只能由特殊事件触发。这些事件由FaaS框架定义,例如上传文件到对象存储、消息队列接收到新消息、API网关接收到新的API请求等。代码的生命周期很短。比如在我们的AI应用中,从接收到事件后调用FunctionHandler开始,到调用返回,不会有内存驻留进程在运行。另外,公有云提供商也会对代码执行时间进行限制,超过时间后执行代码的进程会被强制销毁。例如,AWSLambda的最长执行时间为5分钟。代码必须是完全无状态的,调用之间不能共享内存状态。我们的AI应用程序首先使用一个全局变量来统计处理图片的数量,每处理一张图片,计数器就加1。使用FaaS后,我们不能再使用任何全局变量或内存数据结构(如Hashmap)在调用之间共享数据,因为代码运行在一个独立的进程中,无法访问对方的内存地址空间。所以我们修改了代码,将全局计数器放在公有云的Redis服务中,增加了代码的复杂度。水平扩展不再是问题,FaaS为每个事件和请求运行一个新的代码副本。应用的部署方式从上传和配置整个程序转变为上传打包好的代码文件(如Jar文件或Zip文件)。Serverless给我们带来了什么与传统架构相比,使用Serverless架构重写的AI应用具有显着优势。我们不再运营和维护任何云主机和操作系统,甚至Tomcat等Web容器。我们只需要关注代码本身,所有配置和应用程序生命周期管理都由FaaS框架处理。公有云的出现将我们从物理硬件管理中解放出来,Serverless架构进一步将我们从操作系统管理中解放出来,让我们第一次真正专注于核心业务。业务也变得更加敏捷。我们只需要编写与核心业务相关的代码,比如AI应用中的图像识别部分。无需编写任何代码来加载、部署和配置应用程序。例如,不再需要配置systemd在系统启动时加载应用程序。水平缩放也不是问题。正如上面反复提到的,FaaS框架会为每个事件和每个API请求启动一个新的流程执行代码。这类似于传统应用程序的线程池方法。每个请求都在单独的线程中执行。不同之处在于线程共享相同的内存地址空间,而FaaS进程不共享任何内存。类似于线程池最大线程数的限制,FaaS框架通常也会对最大进程数进行限制。例如,AWSLambda在一个Region中默认可以执行的最大并发调用数是600,这意味着我们的AI应用最多可以运行在600个进程中。同时执行。最后,也是最重要的一点,Serverless架构为我们节省了很多钱。我们只为AI应用程序运行的时间付费,而不是应用程序等待请求的时间。横向扩展的粒度从原来的云主机细化到流程,节省了额外的开支,无需购买闲置的云主机来抵消Auto-Scaling配置不准确的影响。业务敏捷性的提高还降低了运营成本。我们不再需要精通操作系统配置和管理的运维人员,不仅节省了人力成本,也节省了从应用开发到上线的时间。Serverless不是灵丹妙药,而是后端小程序的未来。Serverless架构在某些应用场景中的优势非常明显,以至于一些支持者开始猜测它会成为一种颠覆性的新型云计算架构。技术圈一直都是这样。有些人总是孜孜不倦地寻找包治百病的灵丹妙药,寻找解决一切问题的灵丹妙药。“所有的设计都是关于权衡”,Serverless并不是灵丹妙药,它有着独特的优势,而这些优势也带来了不可避免的局限性。为每个事件/请求启动一个新的进程来运行代码是FaaS的核心,而进程启动延迟是Serverless首先面临的问题。根据编写应用程序所用的语言,启动延迟的范围从10毫秒(例如简单的Python应用程序)到1分钟(复杂的Java应用程序)不等。这样的延迟对于实时程序来说是不可接受的。目前,Serverless应用通常运行在公有云多租户环境中,启动延迟也受系统负载的影响。很难确保应用程序在指定时间内运行。公有云提供商目前不对Serverless提供相应的SLA保证。笔者撰写本文时,AWSLambda并没有相关的SLA条款。Serverless不能用于高并发的应用,每个请求都启动一个进程的开销太大。例如支付宝在双十一高峰期每秒处理8.59万笔交易。如果使用无服务器架构,这意味着我们系统中每秒创建和销毁85,900个进程,这是无法承受的开销。Serverless应用不能驻留在内存中,运行时间有限。如果您的应用程序无法在几分钟内完成工作,那么Serverless不是您的选择。比如AWSLambda给进程的最大运行时间是5分钟,超时后进程会被强制终止。这对编程提出了挑战,例如,我们的AI应用程序必须优化以在5分钟内完成复杂图像的识别。我们也不能编写执行长期IO操作的应用程序,例如对象存储中1T数据的复杂编码。无法在无服务器调用之间共享状态使得编写复杂程序变得极其困难。无状态是互联网应用所追求的目标,比如满足“十二要素”的应用。但是Serverless让无状态更加彻底,不同调用之间不能共享内存状态,比如使用hashmap。在我们的AI应用中,统计处理图片总数的全局计数器在传统架构中只是一个全局变量,但在Serverless架构中它变成了存储在内存数据库(Redis)中的一条记录,以及更新成本等因素而保证的原子性让我们的编码变得复杂了好几倍。对于大多数云原生互联网应用来说,这种完全无状态的架构是一个巨大的挑战。对于几十万、上百万行代码的充满状态的企业应用,Serverless的无状态状态转换几乎是不可能完成的任务。熟练的微服务架构师都非常熟悉将业务拆分成一个个的服务,也有很多经典书籍(比如《Building Microservices: Designing Fine-Grained Systems》)指导我们如何去做。但即便是他们,面对Serverless架构也会感到头疼。如何将业务拆分成成百上千个独立进程运行且运行时间有限的功能是一个巨大的挑战。而这样的细粒度拆分是否有必要是第一个需要回答的问题。有些问题可能变得无法解决或成本极高,例如分布式数据库事务。以上是无服务器架构的一些固有局限性。它们起源于Serverless架构的特点,随着时间的推移和技术的进步很难解决。此外,Serverless作为一项新技术,也面临着集成测试困难、VendorLock-in、调试监控困难、版本控制等诸多不足,每一个都会成为采用Serverless架构的障碍。由于这些限制,Serverless架构不会成为复杂应用的首选,相反,它应该是小型后端程序的未来。云应用有大量的小程序场景,比如识别一张图片,一段音视频编解码,IOT设备请求返回一小段数据,工单通知客服等客户通过email等方式提交。这些事件触发的小程序在传统架构下实现起来比较复杂,往往需要20%的核心业务去运营80%的配套业务。Serverless完美的解决了这些问题,它可以成为复杂应用的补充架构。我们可以将无状态和事件触发的服务拆分成Serverless应用,让整个架构更加简洁高效。Serverless也在不断发展。比如AWS最近推出的StepFunctions,试图解决调用间共享状态的问题,效果如何还有待观察。Serverless不是传统的PaaS。无服务器和PaaS之间的界限是模糊的。许多人认为Serverless是一种PaaS。我也倾向于认为Serverless是PaaS的一种特殊形式。Serverless由两部分组成:BaaS和FaaS。BaaS负责提供业务依赖的服务,FaaS负责业务部署和生命周期管理。从这个意义上讲,Serverless的作用与PaaS是一样的。与传统PaaS的区别在于,传统PaaS是在程序层面管理应用的生命周期,而Serverless是在功能层面管理应用的生命周期。传统PaaS中的应用程序是驻留在内存中的进程,而Serverless应用程序运行后即被销毁。另外,在使用传统PaaS时,用户还需要关心横向扩展,比如如何配置Auto-ScalingGroup,而Serverless则没有这个问题,横向扩展是架构的天然功能。Serverless与微服务Serverless与微服务没有直接关系,但它们有相似之处,比如需要业务拆分、强调无状态、敏捷特性等。在很多方面,Serverless比微服务具有更细的粒度和更严格的要求。比如微服务是在服务的基础上拆分业务,Serverless是在功能的边界上拆分业务;微服务可以跨调用共享内存状态,而无服务器要求调用是完全无状态的。此外,Serverless依赖BaaS提供第三方依赖,而微服务可以自由选择第三方依赖的来源,比如使用本地构建的传统中间件栈(比如本地MySql和消息总线)。Serverless和容器Serverless和容器是苹果和橘子,不在一个平面上。Serverless是一种软件设计架构,容器是软件架构的载体。虽然没有公开资料,但我们可以推测像AWSLambda这样的serverless框架一定程度上使用了容器技术,否则很难做到语言无关和毫秒级启动。虽然一些开源项目已经使用Docker来实现Serverless的FaaS部分,但我认为AWSLambda等公共无服务器框架不会直接使用Docker。它必须是一种更轻量级和更小的容器技术。我们可以称它为纳米容器。无服务器对私有云有意义吗?对于私有云来说,业务迁移到Serverless架构还为时过早。首先,Serverless是从公有云演化而来的新架构,适用于运行在公有云上的小程序。私有云承载了更多陈旧、繁琐的传统业务,这些业务很难用Serverless架构进行改造。其次,Serverless依赖于BaaS。在私有云中构建和运行BaaS的成本并不低。使用公共BaaS服务受限于网络带宽和延迟,容易导致系统不稳定。随着企业应用的进一步云化和开源Serverless框架的成熟,Serverless也可以作为私有云devops场景中的CI/CD。比如目前Jenkins承担的大部分工作都可以被serverless代替,比如使用FaaS框架对应Jenkins本身,上传的代码对应JenkinsJob中的Bash脚本,原有的JenkinsAPI触发Job触发FaaS中的代码。总结Serverless作为一种全新的架构,是云计算发展演进的必然结果。云计算的趋势是追求更细粒度的计费单位,更专注于核心业务,将支撑业务外包给基础设施提供商。Serverless架构的特性使得编写事件触发的后端小程序变得更加容易。同时,它也有其固有的局限性,不适合复杂的应用架构。从目前的情况来看,部分采用Serverless的混合架构对于公有云应用来说是一个不错的选择,对于私有应用采用Serverless还为时过早。云计算技术发展迅猛,未来有无限可能。
