微服务的生态和实践已经比较成熟,其设计方法、开发框架、CI/CD工具、基础设施管理工具等,都可以帮助企业顺利实施微服务。然而,微服务远没有达到完美,它在架构、开发、基础设施方面仍然面临新的挑战。
微服务的粒度影响服务的交付速度及扩展性,微服务的开发引入治理组件,增加了开发的难度,以容器为基础的微服务基础设施在弹性等方面仍有不足,而微服务增加带来的基础设施成本也是微服务实施的新挑战。
1.微服务的粒度仍然比较大
当前微服务划分主要遵循单一职责的原则,比如将用户管理的功能作为一个单独的微服务。如图所示,用户管理微服务提供了API注册、登录、登出功能。通常,从提升用户体验的角度来看,浏览器会保留用户的会话,除非用户主动登出,否则不会请求登出API。所以,登出和注册的QPS差距较大,对扩展的诉求完全不同。而且,注册API和登出API的变更频率也可能不同。进一步拆分可以带来扩展性等便利,但整个微服务的数量也会提升一个量级,给基础设施的管理带来负担,那么如何做好架构权衡,既能够拥有架构上的高可扩展性,又不用增加基础设施管理成本呢?
2.微服务开发仍有较高门槛
如图所示,Java微服务开发的软件栈要求开发者掌握以下技能。
Java微服务开发技术栈
相比于单体应用开发,微服务开发效率得到提升的部分来自服务粒度减少及开发框架的改进,例如,从复杂的SpringMVC演进到SpringBoot,框架更加轻量化。但在其他方面(并发处理等)并没有什么改变,同时在微服务治理、分布式事务等方面的开发难度反而增加了。服务网格的出现,让开发人员可以不用关心服务治理的内容,但这样会带来服务性能的下降和维护的复杂性,其使用的范围也存在局限。是否存在一种新的编程模型及开发框架,让开发者在了解基本的语言特性和编程模型后,便可上手开发业务逻辑,而不用关心网络、并发、服务治理等问题?
3.微服务基础设施管理、高可用和弹性仍然很难保证
容器和Kubernetes工具的使用,提升了应用部署及基础设施运维自动化的能力,但保证基础设施高可用、可扩展对运维人员的能力要求很高。如图所示,服务上云后,基础设施团队可以不用再关心服务器、交换机等硬件的运维,但仍然需要关心虚拟机的维护,如安全补丁、基础镜像的更新升级、扩容等。
基础设施团队依然需要管理虚拟机
从On-Premise到公有云,实际上虚拟机的可用性在降低,比如云服务商提供的单虚拟机的可用性可能只有95%。运维人员需要借助云侧的工具来保证基础设施的高可用,难度仍然存在,而且很依赖运维人员的能力。
集群及其他云原生工具的维护也带来额外的挑战。以Kubernetes集群为例,维护和管理Kubernetes集群需要专业的技能。同理,维护云原生的监控、日志服务的高可用性也有不小的难度。所以,基础设施管理的难度仍然存在,只是从虚拟机转移到容器集群,从Rsyslog转移到ElasticSearch。
对于服务层面的扩展性,当前的策略也比较简单,例如,设定最少和最多使用的虚拟机数量,或者想办法改善根据CPU/内存使用率来伸缩或扩容的延迟。但是,由于总体资源量不会超过策略设定的虚拟机极限数量,因此一旦请求超过最大资源能承载的范围,可能会影响用户的使用体验甚至会服务中断。以容器为单位的扩容,从虚拟机性能的分钟级减少到30s左右,但当面对突发流量时依然会出现响应不及时、用户体验差的情况。是否存在全托管的基础设施及监控运维服务,能提供更好的弹性,从而让开发者无须关心所有底层和集群的维护工作,不再依赖高级运维人员来保证基础设施的可用性?
4.基础设施的成本依然较高
微服务会增加基础设施的成本。每个微服务都要考虑冗余,保证高可用。随着微服务数量的增加,基础设施的数量会呈现指数级增长,但云服务的基础设施收费方式没有改变,依然采用按照资源大小及以小时为单位(或包年)计费的方式。闲时和忙时的收费相同,对企业来说存在成本的浪费。是否存在一种新的基础设施服务,能按照“用多少付多少”的方式收费,从而降低基础设施成本?
微服务面临的这些新问题,是否可以通过新的基础设施服务及开发模式来解决呢?
2012年,时任Iron.io的副总裁Ken提出了Serverless的概念,他认为未来的软件和应用都应该是Serverless的:“即使云计算兴起,世界仍然围绕着服务器运转。不过,这不会持续下去。云应用程序正在进入无服务器世界,这将对软件和应用程序的创建和分发产生重大影响。”
2014年,AWS推出Lambda函数计算服务,提供简化的编程模型及函数的运行环境全托管,并且计费方式更加接近实际的使用情况(请求次数和每100ms使用的内存资源)。2015年,AWS推出API Gateway(全托管的网关服务),正式将Serverless这个概念推广开来。近年来,大部分的云提供商也提供了各种形态的Serverless服务,用于支持更多应用的开发和运行。下图为AWS Serverless全景图。
AWS Serverless全景图
Google在Serverless上的投入和发展节奏也很快。为了扩大在移动应用开发领域的优势,同时为Google云引流,Google在2011年就收购了Firebase,2016年将其作为mBaaS(移动后端即服务)的Serverless解决方案推出,以及安卓应用开发的主流云服务。除此之外,Google也推出了其他Serverless服务,以提供跨平台(Android、Web、iOS等)能力,支持移动、Web等应用开发,下图为Google Serverless全景图。
Google Serverless全景图
华为终端云服务以多年为超过百万移动应用开发者提供服务为基础,结合多年在Serverless领域的技术积累,推出了Serverless行业解决方案,包含构建类(云函数、认证、云存储、云数据库等)、增长类(推送服务、远程配置等)、质量和分析类(性能服务、崩溃服务等),提供面向移动应用开发的Serverless服务。2021年,云函数、云数据库等核心构建类服务已面向全球HMS生态的开发者开放,下图为HUAWEI AppGallery Connect Serverless全景图。
HUAWEI AppGallery Connect Serverless全景图
Serverless的定义
那么Serverless到底是什么呢?维基百科将Serverless定义为一种云计算执行模型。
CNCF(Cloud Native Computing Foundation,云原生计算基金会)认为Serverless旨在构建和运行不需要服务器管理的应用程序,二者的不同之处在于它描述了一个更细粒度的部署模型,能够以一个或多个函数的形式将应用打包并上传到平台执行,并且按需执行、自动扩展和计费。
Serverless并不意味着不需要服务器来托管和运行代码,也不意味着不再需要运维工程师。Serverless是指开发者不再需要将时间和资源花费在服务器调配、维护、更新、扩展和容量规划上,这些任务都由Serverless平台处理,开发者只需要专注于编写应用程序的业务逻辑,运维工程师能够将精力放在业务运维上。综合维基百科和CNCF的定义,可以认为Serverless是一种云计算执行、部署和计费模型,Serverless服务按请求为应用分配资源,按照使用计费,基础设施全托管(无须关心维护、扩容等)。
目前,Serverless服务主要分为FaaS和BaaS。
FaaS与IaaS、PaaS的区别
FaaS通常是承载业务逻辑代码的服务,开发者会更为关心,它也是本书重点介绍的内容。
下图是典型的Serverless系统架构,从中可以看到一些Serverless的常用概念。
典型的Serverless架构
结合上图中典型Serverless架构的架构元素,从Serverless系统的实现来看,其关键技术需求包括以下几点。
虽然业界涌现的各种Serverless系统在实现上可能有所不同(如本节介绍的多个函数计算平台),但基本的概念、原理和关键技术是相通的,各个系统在实现时都需要应对以上所述的技术挑战。
从开发者或商业的角度看来,Serverless的价值在于全托管及创新的计费模式。但从技术的角度看,Serverless从架构、开发模式、基础设施等层面都有不同程度的创新。
Serverless基于事件驱动的架构,它的编程模型和运行模式简化了开发模式,融入了不可变基础设施的最佳实践。
1.Serverless是事件驱动架构的延伸
Serverless更容易实现事件驱动的应用。在分布式系统中,请求/响应的方式和事件驱动的方式都存在。请求/响应是指客户端会发出一个请求并等待一个响应,该过程允许同步或异步方式。虽然请求者可以允许该响应异步到达,但对响应到达的预期本身就在一个响应和另一个响应之间建立了直接的依赖关系。事件驱动的架构是指在松耦合系统中通过生产和消费事件来互相交换信息。相比请求/响应的方式,事件的方式更解耦,并且更加自治。例如,在图片上传后进行转换处理的场景,以往需要一个长时运行的服务去轮询是否有新图片产生,而在Serverless下,用户不需要进行编码轮询,只需要通过配置将对象存储服务中的上传事件对接到函数即可,文件上传后会自动触发函数进行图片转换。
Serverless架构的基本单元从微服务变为函数。微服务的每个API的非功能属性有差异,比如对性能、扩展性、部署频率的要求并不相同,进一步拆分的确有助于系统的持续演进,但相应会带来指数级的服务数量增长,导致微服务的基础设施和运维体系难以支撑。Serverless架构可以将微服务的粒度进一步降低到函数级,同时不会对基础设施和运维产生新的负担,只是增加了少量的函数管理成本,相比其带来的收益这是完全可以接受的。
基于Serverless更容易构建3-Tier架构应用。3-Tier是指将应用分为3层,即展示层、业务层及数据层,并且会部署在不同的物理位置。如Web应用,其展示层和业务层在物理层面往往会在一起部署。以下图中的宠物商店应用为例,在基于微服务的部署视图中,其业务层和展示层在一起部署;而在基于Serverless的部署视图中,展示层可以托管在对象存储服务中,业务层由FaaS托管,数据层由云数据库托管,实现了3-Tier在物理上的独立部署。同时,各层独立扩展,技术独自演进。
通过Serverless构建三层架构的宠物商店应用
2.Serverless简化了开发模式
微服务提供了丰富的框架,方便开发者进行开发,但同时也增加了开发者的认知负担,同样是使用Java,基于Serverless开发服务,开发者只需掌握Java的基础特性、函数编程框架及BaaS的SDK即可,如下图所示。
基于Java的微服务开发和函数开发差异
函数的编程框架相比Spring/SpringBoot要简单很多,开发者只需了解输入输出处理(通常为JSON)及如何处理业务逻辑。如下图所示,Serverless系统可以是1∶1的触发模型,每个请求被一个单独的函数实例处理,每个实例可以被视为一个单独的线程,系统自动根据请求数量扩展函数实例,开发者不用理解Java的并发编程也可以轻松实现对高并发应用的支持。
Serverless支持应用的高并发
基于函数的编程模型,可以继续对数据进行抽象操作。例如,Azure Function提供的Data Binding功能,允许开发者用一套配置和一种编程模型操作不同存储服务的数据,让开发服务变得更加简单,降低开发人员的认知负担,进而提升开发效率。
3.Serverless是不可变基础设施的最佳实践
Serverless直接以代码方式部署,开发者不用再考虑容器镜像打包、镜像维护等问题。系统通常在部署时重新创建函数实例,在不使用时回收实例,每次处理用户请求的可能都是全新的实例,降低了因为环境变化出错的风险。而这些部署及变更的过程,对用户来说只是更新代码,其复杂度相比使用容器及Kubernetes大大降低。Serverless在扩展性方面也具有优势。FaaS和BaaS对开发人员来说没有“预先计划容量”的概念,也不需要配置“自动扩展”触发器或规则。缩放由Serverless平台自动发生,无须开发人员干预。请求处理完成后,Serverless平台会自动压缩计算资源,当面对突发流量时,Serverless可以做到毫秒级扩容,保证及时响应。
基于Serverless的服务治理也更简单。例如,通过API网关服务可以对函数进行SLA(服务水平协议)设置限流,函数请求出错后会自动重试,直至进入死信队列,开发者可以针对死信队列进行重放,最终保证请求得到处理。
Serverless平台默认对接了监控、日志、调用链系统,开发者无须再费力单独维护运维的基础设施。虽然当前Serverless的监控指标并不如传统的监控指标丰富,但是其更关注的是应用的黄金指标,如延迟、流量、错误和饱和度。这样可以减少复杂的干扰信息,使开发者专注在用户体验相关的指标上。
除了以上的技术创新,Serverless还有一些额外的优点。
为了说明Severless开发与微服务开发的区别,表1-1对比了整个软件开发流程中微服务和Serverless在每个阶段的活动,从设计、开发、上线到持续服务,Serverless相比微服务在开发难度及工作量上大幅降低,最终体现为更少的业务上线时间和更稳定的运行质量。
微服务和Serverless开发的差异