摘要:Serverless能够给企业客户和开发者带来非常直观的收益,包括成本节约和效率提升。
作者:冯嘉
通常意义上来讲,Serverless 可以看作是一种云计算服务模型,它允许开发者在不需要管理服务器的情况下通过事件驱动的方式运行代码。与传统应用服务开发模式不同,开发者只需编写并上传他们的应用代码到云服务商提供的平台上,云平台会自动为应用分配资源,并处理应用的部署、扩缩容。这使得开发者可以更加专注于自己的业务需求和应用逻辑,而不需要考虑服务资源的申请、创建、管理和维护等。从这个意义上讲,我们也可以认为Serverless是一个计算范式,它解决资源托管、调度、运维管理等一系列平台型问题,可以看作是DevOps的进一步延伸。
从应用开发视角来看,Serverless包括FaaS (Function as a Service) 和 BaaS (Backend as a Service) 两部分。在FaaS中,开发者编写的代码会被封装成一个或多个函数,运行在云平台上。当请求到达时,云平台自动为函数分配计算资源,拉起函数并执行。执行完成后,平台根据一定的保活策略决定资源的复用或者释放。FaaS模型不仅可以提高应用的可伸缩性和弹性,还可以大幅降低应用运维的成本。BaaS则致力于更广泛意义下的Serverless化,包括对象存储、缓存、数据库、消息等全栈后端服务的按需弹性、按用付费等。
谈到serverless发展历程,从2008年Google推出App Engine算起,至今已有15年的时间,期间经历了多次迭代,主要经历了以下几个阶段。
从各大云厂商提供的Serverless产品看,目前主要有FaaS、Serverless应用托管和Serverless容器等Serverless服务形态。
FaaS是发展较早的一个方向,它的特点是开发者以函数为粒度对应用进行封装,在无需管理服务器等基础设施的情况下运行函数,支持毫秒级弹性扩容,同时也是三类技术中与事件驱动架构结合最紧密的,例如AWS Lambda与EventBridge的深度集成,华为云FunctionGraph与EventGrid的生态合一等,因此,早期的FaaS服务往往适用于需要快速响应的事件驱动式场景,如文件上传、消息发送和定时任务。
Serverless 应用托管主要为应用提供全生命周期管理的能力,代表性服务如Google App Engine, 华为云CAE (Cloud Application Engine) 等,主要提供面向应用的Serverless托管服务,提供秒级部署、极致弹性的一站式应用托管方案,往往多用于Web应用程序和移动应用后端等场景。
Serverless容器服务是近几年发展起来的新服务形态,特点是可以让开发者在无需管理和维护集群的情况下,快速创建容器应用 (如Kubernetes容器),是一种Serverless化的容器管理能力,主要适用于DevOps、CI/CD 等业务场景。
从业务场景看,每种服务都有自己擅长解决的问题域,正如软件复杂性所讲的那样——No Silver Bullet,Serverless技术正在不断持续演进。
FaaS对基础设施的抽象程度最高,企业在使用过程中的运维负担相对最小。Serverless容器则开放了更多资源配置的灵活性,但可能会给开发者带来一定程度上的关注疲劳。我们都能看到,随着企业级应用开发的SOA时代逐步演进到微服务时代,应用的打包、分发与运行等细节逐步被托管态服务隐藏,人们甚至不用关心底层用的是Tomcat、jetty 还是undertow容器。
我个人认为,Serverless走向架构统一是对用户更加友好、并能缩短企业核心业务 GTM (Go-to-Market) 时间的最佳做法。正如FaaS和应用托管长在Serverless容器之上,Serverless容器向下专注于底层资源池的自动化管理和弹性伸缩。“让专注更加专注”。随之而来的,一种新的支撑通用全场景的Serverless服务模型应运而生,新serverless 时代终将到来。
如前所示,Serverless当前仍处于快速发展中,无论是框架、平台、开发工具,还是服务在内的生态集成,都还未形成事实上的开放标准与规范。在推动Serverless更加成熟、可靠和易用的过程中,开源依旧发挥了举足轻重的作用。
底层沙箱方面,有Firecracker、gVisor、Kata Container和WASMEdge等优秀开源项目,它们在不同程度上关注轻量级、安全隔离、快速启动以及与其他容器编排工具(如Kubernetes)的兼容性,虽各有侧重,但总体目标是为Serverless应用程序提供一个安全、高效的运行环境。
Firecracker最初被设计为解决裸金属EC2上微服务或者无服务架构的应用现代化问题提供支撑。基于VirtIO网络,磁盘和套接字驱动,Firecracker用rust重写了日益庞大且复杂的VMM实现QEMU,采用guest模型允许用户访问KVM的最小元素。这也是为什么Firecracker被称之为MicroVM沙箱技术。每个 MicroVM 都是以 KVM 进程的方式运行,由操作系统负责进程调度。为了与容器标准兼容,Firecracker允许RunC 容器(或者Pod)运行在其内部,通过 HostOS 上的 containerd 管理 GuestOS 的容器。从而无缝兼容 OCI (Open Container Initiative) 标准规范,镜像格式以及管理工具。
gVisor为Linux容器提供安全隔离的内核层,主打应用级虚拟化沙箱。作为一个普通的用户态进程运行,gVisor通过实现内核原语(信号量、文件系统、Futex、管道等)的方式,把应用程序的系统调用重定向给主机内核。Kata 则结合了容器的轻量级优势和虚拟机的安全隔离性能,可以与Docker和Kubernetes无缝集成,对于IO密集型调用更高效友好。本质上讲,这些通过在用户态运行一个操作系统内核(裁剪抑或全功能)来为应用进程提供强隔离的思路正在成为安全沙箱的默认选项,只是在实现方式上,需要权衡好安全、性能与扩展开销。
与之前介绍的实现思路不同,作为WebAssembly经典的运行时代表,WASMEdge旨在寻求面向边缘场景的进程级虚拟技术的定位,也是我个人非常看好的方向之一。虚拟机模拟了计算机,容器模拟了操作系统,WASM则模拟了进程。不难看出,沙箱技术的发展本质上也在推动虚拟化技术的不断发展。近些年来,随着硬件卸载虚拟化技术的日趋成熟,沙箱技术必将演进到一个全新的高度。这也是我个人非常期待看到的。
往上,在运行时层,Google通过开源Knative,为Kubernetes提供Serverless扩展,包括可组合、可扩展的Serverless构建和运行时组件,以及与Istio服务网格的集成。Knative可以看做是对标准化Serverless运行时的一次尝试,是一个独立于底层平台的Serverless框架,可以部署在多种基础设施之上,包括Kubernetes、Mesos和Docker Swarm。
Fission则围绕Kubernetes,主打简化Serverless应用程序的开发、部署和管理过程,提供简单易用的Serverless体验。我们也在尝试考虑开放内部的函数计算平台,通过批流一体的大规模调度、近数据亲和计算等技术,来解决现有框架无法支持高性能大数据处理等场景的瓶颈,让Serverless走向支持更加通用、多场景复杂应用的时代。
其它一些项目主要聚焦应用开发体验,如Serverless Framework, Serverless Devs。这类工具帮助开发者实现快速创建Serverless应用,并简化调试、部署、调测定位等。过去一年,我们联合上海交大、信通院推出了跨平台的Serverless基准测评平台Serverless Bench 2.0,通过对不同 Serverless 平台之间的异构性进行封装,包括统一函数接口、统一返回格式、统一资源配置等,为开发者提供了快速对比不同Serverless产品差异化优势的能力,帮助企业设计并开发出更加高性能、低成本的 Serverless 应用程序。
我们都知道,前两次生产力革命,分别大幅提升了劳动者生产力与组织的生产力。第三次生产力变革,大幅提升了品牌的生产力。借用德鲁克的用语,即开启了“心智力量战略”。在竞争激烈的市场中,通过新的定位重塑整个产品的案例不在少数。基于这样的背景,我认为新轮子的出现有其一定的必然性。不同的Serverless产品和方案纷纷涌现,各自展现出独特的特点和优势,正是这种积极的、良性的竞争,推动了技术的不断升级和完善。在这个过程中,企业可以通过明确自己的业务目标、市场定位以及受众目标,来确定能够为自身业务带来最大价值的Serverless平台。
由于 Serverless 架构的特点,应用实例在长时间不使用后会被自动回收 (Scale-to-Zero),新的请求到来时,有一定概率需要重新创建实例,整个过程会带来一定的冷启动延迟。通常,客户的Java类函数、Web型应用对极致冷启动性能有较高的需求。Serverless冷启动问题通常需要厂商和企业共同承担 (Shared Responsibility), 这由冷启动时延开销的构成所决定。一般地,冷启动过程包括沙箱启动、沙箱初始化、应用代码/镜像加载(包括下载、解压、依赖载入等)、应用代码初始化、请求执行等步骤。其中,企业在减缓应用代码加载、应用代码初始化的耗时方面,比厂商有更强的可操作性和灵活性,包括对应用进行瘦身,如消除冗余代码、减少非必要依赖的使用,以降低代码下载、解压时延。企业开发者也可以尽可能将初始化数据库链接、初始化存储等相关代码片段,放到函数调用入口之前,避免每次冷启动重复执行这类耗时操作。
云厂商在冷启动问题上,推出了一系列解决方案。
其它措施还包括对应用镜像或代码进行缓存、采用高性能解压缩算法、公共依赖包分离,及按需加载技术等。关于Serverless冷启动,我们近期会发表另外一篇技术文章进行更加系统和深入的介绍。
我们之前讲,尽管Serverless提倡无状态优先,但随着数据密集型应用逐渐成为云上应用的主流,如大规模机器学习、大数据与流处理、实时交互型应用、多人协作类应用等,分布式状态管理是无法回避的任务,而且复杂度很高。开发者既希望在这类应用中发挥Serverless解决方案的优势,又不想自己处理门槛较高的状态维护问题,因此对Serverless平台支持有状态、自动化状态管理的诉求越来越强烈。
FunctionGraph是业界首个支持有状态的Serverless函数产品,用户可以在函数配置界面开启有状态开关,并在函数代码中编写少量状态初始化的init代码;之后, 整个状态管理将由FunctionGraph接管,平台为函数状态设定独立的key,状态key具有单独的状态路由,平台根据状态路由,对事件请求进行调度。有状态函数为开发者提供了多种状态一致性模型和自动化的并发处理机制,整个状态管理过程由平台内置提供,无需与外部存储服务之间进行频繁交互,显著减少了涉及大量状态数据操作的网络访问次数,具有自动化、高性能、高可用等特点。
“伸缩原子轻量化”是个“功能性”概念,与事件驱动架构是紧密关联的。以FaaS为例,主要指“让一个函数尽可能只做一件事”,如果应用需要完成多个功能,则应尽可能拆分成多个函数实现,多函数间通过工作流编排进行逻辑组合。事件驱动模式下,函数通常具有“即生即灭”的特点,随事件触发而生,随响应结束、保活到期而灭。让单个函数保持功能单一,逻辑内聚,不仅能够支持快速的“独立”扩缩容,也能够最大限度地使得应用的各个微服务函数“按需”扩缩容。
举个例子,假设一个应用包含两个微服务函数A和B,分别实现两类功能,对应内存资源均为1G。当函数A的事件流量增大导致实例需要扩容时,可以对比两种方案下的成本:第一种方案下,函数A和B作为两个函数独立伸缩,此时只需对函数A进行实例扩容,资源成本以1G为步长进行累加;第二种方案下,函数A和B被封装成一个内存大小为2G的函数,此时扩容,资源成本将以2G为步长进行累加,最后总成本也会显著高于第一种方案。本质上,在第二种方案下,函数A和B由于功能耦合导致资源扩容互相绑架,从而造成额外的成本浪费。
FinOps是一个相对较新的概念,主要聚焦云上资源管理和成本优化,通过有机链接技术、业务、和财务专业人士,来优化用户、企业、组织的云资源成本,提高云上业务的投入产出比。
我们之前发表过一篇文章《Serverless 遇到 FinOps: Economical Serverless》,里面有提到FunctionGraph为帮助用户实现FinOps目标所采取的具体技术和措施,包括用户函数成本研究中心(Cost Analysis and Optimization Center),离线式函数最佳配置调优(Offline Power Tuning)、在线式资源消耗感知与规格动态推荐(Online Resource Recommendation)、预留实例智能推荐(Intelligent Recommendation Policy)等,最大限度降低用户实现应用 FinOps 的门槛,为用户业务开发、Serverless 化改造等提供极致便捷性。
另外,Serverless本身免运维、自动弹性和按需计费的特点,核心也是帮助企业在保障应用性能与稳定性的前提下,消除成本浪费,因此,采用Serverless化的架构及其解决方案,本质也是在践行FinOps的理念。
除上面提到的冷启动问题,云厂商和开源社区都在加强对Serverless技术和产品的改进,以下举几个例子:
关于Serverless适合场景与选择,市面上已经有很多解读。这里,结合我们的一些客户视角,谈谈其中的几个可能的关键考量:
从决定采用Serverless架构,到企业完全掌握之间,通常会经过一个短暂的适应。例如,企业可以先在一些小的项目中试用Serverless,比如使用函数构建一个简单的Web应用,通过小规模的测试和验证,感受Serverless架构的优点和适用场景。然后从业务场景中选择能够使用 Serverless 架构解决的子问题,逐步将现有应用程序的组件迁移到Serverless,如数据处理、日志分析、或消息队列处理等,提高对Serverless的应用能力。验证成功后,再快速复制、应用到其它业务场景中。对于全新的项目,也可以直接采用Serverless架构,这时只需专注自己业务逻辑的设计与编码,体验快速构建应用及其上线与发布。
有时候企业为了满足特定的业务需求,需要定制化的 Serverless 解决方案,或企业希望完全掌控自己的代码和数据,避免供应商锁定等时,选择在开源产品的基础功能上进行二次开发,以缩短开发周期。
然而,二次研发需要企业具备相关的技术能力,包括对Serverless技术栈的掌握和对开源Serverless产品的理解。同时,应用维护成本通常较高,企业需要自己承担Serverless平台本身的维护和升级成本,难以真正发挥Serverless免运维的优势。此外,开源产品通常由社区开发和维护,缺乏高效稳定的技术支持和服务保障,二次研发也面临一定的业务连续性风险。
采用云上成熟的Serverless服务,企业可以聚焦于业务需求和应用逻辑本身,无需再感知或维护底层的基础设施,如虚拟机,容器和Serverless运行时;并可以通过对应用所依赖的其它云服务(如网关、存储、消息和缓存)进行灵活编排,来尽可能减少定制化代码的开发,显著降低代码维护负担。更重要地,云化服务可以为企业提供更加高可靠、可扩展、安全稳定的应用运维体验,以及相应连续、稳定的厂商技术支持,从而在企业业务规模化增长的过程中,降低应用运维的总成本。
这里可以举一些经典的客户案例。一家专注于大规模日志采集与结构化处理的企业,在推出自己的Serverless化日志流式ETL服务的过程中,早期采用了基于开源Knative框架的自建方案,但由于自建方案的资源扩容效率低、底层虚机维护门槛高等问题,使得ETL服务的运维效率低,同时成本居高不下。在采用基于FunctionGraph的云化方案之后, 其ETL服务TOC(Total Ownership Cost)降低了近40%。另一个案例是一家云地图处理服务提供商,采用FunctionGraph对地图处理过程中的异步请求状态进行持久化,相比于早期采用的自建方案,降低了服务TOC近30%。
企业在选择云厂商的 Serverless 产品时,需要结合自身的业务特点和应用架构,可以从以下几个方面考虑:
其它需要注意的地方还包括产品是否具备符合企业核心需求的差异化特性,包括支持硬件加速(如AI类业务对GPU的诉求)、是否支持函数编排(如FunctionGraph Workflow)、是否支持自动化的状态管理等。
从用户反馈看,通常企业既希望享受开发单体应用或单机程序的便捷性,又希望发挥分布式应用的可扩展性、容错性等优势,因此,在产品选择中企业可以关注Serverless平台是否支持自动化的分布式能力,如FunctionGraph提供的单机函数自动分布式化特性。值得注意的是,Google近期针对微服务场景下单机应用分布式化所开源的Service Weaver项目,反映了同样的理念。
通常意义上我们讲,开放或者开源可以避免厂商锁定。我个人也有10年多的开源软件经验,通过开放/开源的方式可以更好地触达到开发者,一则加速产品创新,一则也可以形成良好的品牌效应。但当他们进一步提出可服务要求的时候,还是会综合考虑选择一家可靠的云厂商进行兜底服务。这个道理很容易理解,就像当年个人主机DIY时代,像Dell、IBM这种巨头公司仍然生存的很好。对于Serverless这种新的计算范式的出现,天生就伴随着开放生态的基因,如编程框架与语言、运行时、可观测性、编码与调度等方面。华为云FunctionGraph基于标准的事件驱动模式,对开放标准进行了大量的创新优化与加固,如毫秒级冷启,全链路监控与诊断,高密度调度,极致弹性等。当然,我们在开放标准方面也投入了大量人力,尤其在轻量级沙箱,Serverless编排等方面积极推动相关开放/开源标准的持续升级。我们欢迎任何人随时可以从开源快速迁移到云上,以便享受更优秀的技术创新与服务。
对于企业而言,Serverless主要免除了对底层基础设施的运维,包括计算资源、存储、网络等,通常也免除了对公共依赖服务的运维,如API网关、缓存、消息、事件网格和日志、监控、链路追踪服务等。而企业需要对应用本身进行监控、调试、维护和升级,以确保应用运行符合预期。 不过,在应用全生命周期管理的过程中,云厂商会为企业提供实现深度可观测性的工具和基础设施。
以FunctionGraph为例,通过集成华为云APM(Application Performance Management)服务, 企业开发者可以便捷地为应用执行时延、请求并发度、实例个数、CPU/内存利用率等配置监控指标,对应用进行实时的性能监控;通过内置支持LTS(Log Tank Service)服务, 为应用提供秒级日志搜索、日志转储等功能,使得企业可以进行高效故障管理和调测定位。同时,为了满足企业对扩展性的需求,FunctionGraph也支持开发者通过编写扩展程序来对接第三方的SaaS应用和服务,如Apache SkyWalking, DataDog等,从而可以灵活地按需定制功能更加丰富的高阶可观测性能力。
Serverless可以有效降低企业的运维负担,从而降低应用TOC。在使用 Serverless 时,企业开发人员将采用新的应用开发和部署方式,包括Serverless编程模型、开发工具、运维流程和工具链等;同时,事件驱动架构、按需计费等理念的优势会进一步提高企业应用迭代的敏捷性与经济性。
这里可以分享几个FunctionGraph用户在采用Serverless方案后的真实反馈,数据来自我们去年发起的一次客户调研:
“我们的版本迭代速度明显加快了,以前发布一个新功能,前后至少需要一个月,现在最快能够做到天级别,我们能够更快地响应市场和用户需求。” - 某车联网企业
“对我们来说,降低运维成本是感知最强烈的一点,架构改版之前,我们的运维人员经常在机器维护和资源容量规划的专项中焦头烂额,用了函数之后,这部分人力基本都释放出来了。”- 某云地图服务提供商
“不用再为过度预置的资源所造成的浪费而感到焦虑了。”- 某互联网音频服务提供商
“从我们内部的实践效果看,流式日志分析与Serverless的理念可以有完美的结合。没有接触函数之前,我们日志计算、存储和可视化的整个链路是非常复杂的,投入了很大的精力在稳定性保障专项中。函数化改造后,大部分能力直接用平台提供的,自动扩容,我们主要就是配个告警。”- 某日志处理公司
“我们把微服务的几个模块拆分出来,放到函数上,发现效果很好,也不用再去管理容器资源,低频访问的模块直接缩容到零,成本有显著改善,所以正在迁移剩下的几个模块,后面都是Serverless化的。”- 某SaaS企业
我们在实践中已经看到,Serverless能够给企业客户和开发者带来非常直观的收益,包括成本节约和效率提升。但普及度和接收度的扩展和深入,还依赖一些关键点的解决,包括技术成熟度、领域标准、迁移难度等。这里我们提供一些思路: