摘要
伴随着容器等轻量级虚拟化技术的日趋成熟,云计算正式步入云原生时代。传统以SaaS为核心的云计算模式因其复杂的部署操作和昂贵的运维成本,越来越无法满足人们对于“云”高效率、低成本的要求。无服务计算,又称函数计算、函数即服务(FaaS),是完全依托于云而产生的新型计算模式,其旨在让云平台完全接管应用服务的部署、监控、扩容、容错等工作,从而将开发者的精力完全能转向业务逻辑的开发,解放运维操作;同时无服务计算“Pay-As-You-Go”的运行模式可以为用户节约大量成本。根据CNCF 发布的2020年云原生调研报告,超过60%的企业、组织已经或将要采用无服务计算技术。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图1. 2020 云原生调研报告</figcaption>
由于无服务计算可以便宜、快速、按需的扩展出大量的实例,越来越多的应用,包括数据分析、机器学习训练等,开始转向使用无服务计算。这也使得无状态、完全隔离的无服务计算服务面临诸多性能上的挑战。我们将从运行时、存储与通讯、任务放置与调度等三个方面阐述无服务计算遇到的挑战以及工业界、学术界的解决方案。
一. 无服务计算的兴起
云计算兴起之初,市场上存在两种虚拟化解决方案。一是AWS提供的Elastic Compute Cloud (EC2)[1]服务,二是Google提供的App Engine[2]服务。在当时看来,两种解决方案针锋相对,分别代表了两种极端:EC2实例尽可能的还原物理环境,用户几乎可以掌控从OS Kernel 向上的整个软件栈;而App Engine 则为用户提供了丰富的云端基础服务,用户可以使用这些服务开发云应用。[3]
市场最终选择了AWS的“低级”虚拟化方案,因此谷歌、微软以及国内各大云提供商都提供了类似的接口。虚拟机方案能够成功,归功于在云计算的早期,前景尚不明朗的情况下,用户更多的是希望在云中构建与本地相同的环境,以实现应用迁移,而不是重新开发一套云端应用。[4][5][6][7]
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图2. IaaS、PaaS、FaaS架构比较</figcaption>
然而这种选择的代价是,开发人员必须自己管理整个虚拟环境。表1中列出了云中运行环境必须管理的问题。一系列繁琐的环境管理工作激发了使用简单应用程序的客户对于简单云路径的需求。例如,国庆期间朋友圈迎来了更换国旗头像的热潮。实现一个这样的图片处理程序,可能只需要几十行JavaScript的代码,与配置和维护服务器来运行这段代码的工作量相比,开发工作简直是微不足道的。[3]
表1 云用户搭建环境需要解决的八个问题[3] |
---|
1、可靠性冗余,避免单机故障导致服务中断 |
2、跨区域副本冗余,以保证面临不可抗力时保留服务 |
3、负载均衡,有效利用资源 |
4、自动缩放以响应负载的变化 |
5、监控以确保系统运行良好 |
6、日志记录 |
7、系统升级,包括安全补丁 |
8、迁移到可用新实例 |
基于这种需求,AWS在2015年推出了名为AWS Lambda[8]的云函数服务。引发了业界对无服务计算的广泛,通过Lambda,用户只需要考虑应用程序的代码逻辑,无需考虑扩展、部署、容错、监控、日志记录服务器配置,因而又称之“无服务”计算。
如今,各大云提供商都提供了无服务计算服务。随着越来越多的大型应用,如大数据处理、机器学习模型训练等采用无服务计算的架构,无服务计算的性能问题也日益凸显。[9]
二. 挑战及发展
2.1 运行时
在现有FaaS平台中,每个Function实例都运行在隔离的容器或轻量级虚拟机的环境中,当请求到达时FaaS平台会启动并初始化一个新的实例来响应用户的请求,过程如图三[10]所示。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图3. Serverless 实例的执行流程</figcaption>
这种触发式启动的模式,可以很好的根据负载的变化来自动的扩展或者缩小实例的数目。用户既无需担心流量洪峰时,实例资源严重不足导致的服务质量下降,因为FaaS平台会自动启动足够数目的实例来响应;又可以极大的节省成本,因为FaaS会在低负载时会主动缩减实例,同时无服务计算平台采用Pay-As-You-Go的计费模式,仅对运行过程中资源收费。因此用户无需超配资源,就可以既保证服务质量,又节省成本。更惊喜的是,上述过程无需用户任何的配置,都是由无服务计算平台自动实现,用户只需要提交Function的代码即可!
图4所示,原来的Application直接通过一个线程响应请求,整个过程几乎没有任何初始化的开销。然而对于Serverless而言,需要首先启动一个Sandbox实例,如容器或者轻量级虚拟机,然后初始化Function的运行环境,最后需要通过网络向Gateway传输执行结果,再由Gateway返回给用户。整个过程冗长、且存在严重的冷启动的开销,冷启动的时间甚至超过了Function的执行时间[9]。而且由于原来完整的服务被拆分为数以千计的细粒度Function,冷启动的频率极大的增加!同时由于每个Function实例都具有完整的运行环境,这使得在高并发的情况下,无服务计算的部署密度远小于传统的Serverful服务方式。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图4. Serverless实例与Serverful实例比较</figcaption>
针对解决冷启动问题,主流的解决方案包括:
实例缓存
缓存实例即预启动服务实例,构建一个实例池,从而避免冷启动的过程,如Lambda的预留实例、OpenWhisk的warm-start机制等。此方案可以跳过初始化的过程,但是需要在没有请求的情况下保留足够数量的实例,对于云提供商而言是额外的成本开销!此外,面对超高的突发负载,“池“策略的局限性将进一步凸显,对于超过“池”容量的负载请求,依然需要冷启动实例!
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图5. Openwhisk warm-start示意图</figcaption>
缓存的实例可以分为仅缓存Sandbox和缓存整个Function实例两种。前者具有很好的通用性,缓存的sandbox可以用于处理不同Function的请求,但是无法消除应用的初始化开销[11];缓存整个实例如图5[12]所示,可以完全的消除冷启动的开销,但是通用性极差,放大了池化策略的缺点!
内部并发
在面临突发请求时,启动足够的实例将面临巨大的性能挑战!考虑到单个Function执行所需的资源很小,可以考虑用一个实例并发处理多个请求,从而大大减少冷启动的数目。Knative[13] 融合了原来传统微服务的方式,将一个Function定义为一个更小的微服务,是一个拥有IP的可访问的执行单元,一个function实例可以并发的处理多个用户请求。Knative通过类似于HPA的方式实现了自动扩展,如图6所示。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图6. Knative 自动扩展</figcaption>
每个Fucntion都运行在一个Pod中,Pod运行一个sidecar服务用于监控流量,并周期性向自动扩展组件Autoscaler汇报,Autoscaler 将根据负载情况控制实例的数目。
内部并发,可以减少启动实例的数目,从而减少冷启动开销。但是如何确定实例的并发数目是一个复杂的问题,用户需要根据经验为每一个Function配置合理资源和并发度,这其实于无服务计算的无服务理念相违背。其次HPA的策略需要统计一段时间内的负载变化请款,这就导致实例的扩展总是滞后于负载的变化,面对突发的请求负载,将会导致严重的性能毛刺。
Checkpoint-Restore OnDemand
Catalyzer[11]、Replayable Execution[14]等提出了按需加载的Checkpoin-Restore方案,这是在不破坏隔离性的情况下,真正可以减少冷启动开销的策略。Checkpoint-Restore本身是一个成熟的技术,他会保存应用程序某一时刻的内存状态到持久化存储中,称之为Checkpoint;然后可以通过保存的内存状态恢复程序的运行状态,使之在停止的位置继续运行,称之为Restore。
然而Restore的过程,开销依然存在且无法忽略,如图7所示。因此他们提出了按需恢复的策略,即不在启动的关键路径上完全恢复进程状态。这是出于对进程初始化过程中启动的文件和加载的内存,只有很少一部分会在运行的过程中被使用这一实践情况的观察。最终,该案可以将应用(JVM)的初始化开销,缩减至30ms左右。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图7. Restore的性能开销</figcaption>
轻量级隔离
这是一种以弱化隔离性为代价的解决冷启动开销的方案。SOCK[15]设计了新型的容器模型,阉割了Docker中的部分功能,如使用NAT转发替换网络隔离,使用Mount-Bind替换AUFS的文件系统隔离等;SAND[10]认为,同Application的Function之间不需要强大的隔离,因此设计了一种两层的隔离方案,使用进程隔离Function,使用容器来隔离Application,并通过fork来创建新实例;FAASM[16]则直接将实例放在同一进程地址空间中,使用线程来驱动实例的执行,并通过WebAssembly机制来确保内存安全!
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图8. SADN(L)、FAASM(R)的隔离方案</figcaption>
2.2 存储与通讯
无服务计算的实例是无状态和完全隔离的,这有利于实现按需的自动扩展。然而伴随着无服务计算的应用范围越来越广泛,无状态的特性逐渐成为性能瓶颈问题。由于完全的隔离,实例之间无法直接进行通讯,只能通过第三方的存储服务来传递中间结果,称之为无服务计算的临时存储问题。[17]
通常临时存储的介质包括磁盘、SSD和内存存储。三者的价格依次上升而访问的响应时间依次减小。因此如何选择合适的存储介质,在确保服务质量的前提下,节省最大的成本,是临时存储所面临的主要挑战。Pocket[18] 通过对Function任务的分析,可以帮助用户动态的选择合适的存储方式。
然而即使选择内存存储,用户依然需要使用网络将数据拉取到本地,如果多个Function共享某个中间结果,那么就需要重复的拉取拷贝和数据序列化,如图9所示,这会导致额外的内存开销,降低函数的部署密度。针对这个问题,FAASM[16]基于WebAssembly共享地址空间的特性,设计了共享内存的数据通讯方案。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图9. Function 共享数据会被重复的拉取、序列化</figcaption>
此外Function无法直接调用启动另一个Function,需要首先将调用的请求上传到全局的Gateway中,再由Gateway进行裁决和任务的下发,这就带来了额外的调用开销,如图10所示,对于延迟敏感的任务,这种开销是同样是无法接受的。SAND[10]、Nightcore[19]等实现了本地的消息队列,当本机的资源合适时,可以选择直接在本地启动实例。
<figcaption style="margin-top: calc(0.666667em); padding: 0px 1em; font-size: 0.9em; line-height: 1.5; text-align: center; color: rgb(153, 153, 153);">图10. 无服务计算的链式调用(1)及其开销(2)</figcaption>
2.3 任务放置与调度
数据分析型任务可以根据数据依赖性抽象成一个DAG图,分为多个阶段,每个阶段包含多个并行任务。数据分析型负载通常随着时间的推移资源需求也在变化,因此特别适配于无服务计算平台,可以充分的利用其按需资源分配和快速实例扩展的特性。[20]
然而由于数据分析任务流长且复杂,如果采用“invoke one_by_one”的方式逐一启动实例,会放大冷启动的开销,而如果采用“invoke all”的方式,预启动所有实例则会造成严重的资源浪费。此外任务间存在大量的中间数据传递,间接的数据通信开销巨大。
除前述解决冷启动和通讯的系统方案之外,通过恰当的调度策略,可以在现有系统的基础上优化任务的执行路径,在保证任务服务质量的前提下,节省成本开销。
现有的解决方案主要通过分析任务流的结构,利用任务流内的调用关系以及数据局部性等,决策Function的启动时机和数据传递。
优化启动时机
如下图所示,普通的启动模式分为:懒汉模式和饿汉模式。懒汉模式顺序初始化function,饿汉模式提前初始化function。显然懒汉的成本更低,饿汉的执行时间更短。Caerus[20]通过分析任务间的依赖关系,在何时位置启动下一步实例,重合执行可并发的部分,隐藏启动开销,同时缩短实例的等待时间。
优化数据传递
如下图所示,可以从一个DAG图中分割出多个子图,子图内部的中间数据自下而上的传递。可以让子图中所有任务重用同一个Function实例,对于子图重合的部分,根据数据大小,动态选择数据传递方向,尽量避免不必要的数据传递。[21]
总结
从无服务计算的概念被提出至今已有六年,特别是近三年来涌现了许多相关的研究。各大云平台对于无服务计算的多是基于现有的虚拟化技术和针对VM、容器的编排方法来实现,用有状态、粗粒度的“胖子”来“伪装”无状态、细粒度的“瘦子”。现有的研究多是在特定的场景对具体问题做针对性改进,无服务计算依然无法做到SaaS那样通用性。
参考
- ^Amazon Elastic Compute Cloud. https://aws.amazon.com/cn/ec2. Accessed: 2021.10.8. https://aws.amazon.com/cn/ec2
- ^App Engine. https://cloud.google.com/appengine/ Accessed: 2021.10.8. https://cloud.google.com/appengine/
- ^abcJonas E, Schleier-Smith J, Sreekanti V, et al. Cloud programming simplified: A berkeley view on serverless computing[J]. arXiv preprint arXiv:1902.03383, 2019.
- ^Stephen Orban. Cloud-native or lift-and-shift? https://aws.amazon.com/blogs/ enterprise-strategy/cloud-native-or-lift-and-shift/. Accessed: 2019-01-23. https://aws.amazon.com/blogs/
- ^Christina Delimitrou and Christos Kozyrakis. Quasar: Resource-efficient and QoS-aware cluster management. In Proceedings of the 19th International Conference on Architectural Support for Programming Languages and Operating Systems, ASPLOS ’14, pages 127–144, New York, NY, USA, 2014. ACM.
- ^Jason Mars, Lingjia Tang, Robert Hundt, Kevin Skadron, and Mary Lou Soffa. Bubbleup: Increasing utilization in modern warehouse scale computers via sensible co-locations. In Proceedings of the 44th annual IEEE/ACM International Symposium on Microarchitecture, pages 248–259. ACM, 2011.
- ^Hailong Yang, Alex Breslow, Jason Mars, and Lingjia Tang. Bubble-flux: Precise online QoS management for increased utilization in warehouse scale computers. In Proceedings of the 40th Annual International Symposium on Computer Architecture, ISCA ’13, pages 607–618, New York, NY, USA, 2013. ACM.
- ^ AWS Lambda. https://aws.amazon.com/cn/lambda/ . Accessed: 2021.10.12. https://aws.amazon.com/cn/lambda/
- ^abWang L, Li M, Zhang Y, et al. Peeking behind the curtains of serverless platforms[C]//2018 {USENIX} Annual Technical Conference ({USENIX}{ATC} 18). 2018: 133-146.
- ^abc Akkus I E, Chen R, Rimac I, et al. {SAND}: Towards High-Performance Serverless Computing[C]//2018 {Usenix} Annual Technical Conference ({USENIX}{ATC} 18). 2018: 923-935
- ^abDu D, Yu T, Xia Y, et al. Catalyzer: Sub-millisecond startup for serverless computing with initialization-less booting[C]//Proceedings of the Twenty-Fifth International Conference on Architectural Support for Programming Languages and Operating Systems. 2020: 467- 481.
- ^Squeezing the milliseconds: How to make serverless platforms blazing fast! https://medium.com/openwhisk/squeezing-the-milliseconds-how-to-makeserverless-platforms-blazing-fast-aea0e9951bd0 . Accessed: 2021.10.18.
- ^ Knative. https://knative.dev/docs/ . Accessed: 2021.10.18.
- ^ Wang K T A, Ho R, Wu P. Replayable execution optimized for page sharing for a managed runtime environment[C]//Proceedings of the Fourteenth EuroSys Conference 2019. 2019: 1-16.
- ^Oakes E, Yang L, Zhou D, et al. {SOCK}: Rapid task provisioning with serverless-optimized containers[C]//2018 {USENIX} Annual Technical Conference ({USENIX}{ATC} 18). 2018: 57-70.
- ^abShillaker S, Pietzuch P. Faasm: Lightweight isolation for efficient stateful serverless computing[C]//2020 {USENIX} Annual Technical Conference ({USENIX}{ATC} 20). 2020: 419-433.
- ^Klimovic A, Wang Y, Kozyrakis C, et al. Understanding ephemeral storage for serverless analytics[C]//2018 {USENIX} Annual Technical Conference ({USENIX}{ATC} 18). 2018: 789-794.
- ^ Klimovic A, Wang Y, Stuedi P, et al. Pocket: Elastic ephemeral storage for serverless analytics[C]//13th {USENIX} Symposium on Operating Systems Design and Implementation ({OSDI} 18). 2018: 427-444.
- ^Jia Z, Witchel E. Nightcore: efficient and scalable serverless computing for latencysensitive, interactive microservices[C]//Proceedings of the 26th ACM International Conference on Architectural Support for Programming Languages and Operating Systems. 2021: 152-166.
- ^abHong Zhang, Yupeng Tang, Anurag Khandelwal, Jingrong Chen, Ion Stoica. Caerus: NIMBLE Task Scheduling for Serverless Analytics. In NSDI 21.
- ^Benjamin Carver, Jingyuan Zhang, Ao Wang, Ali Anwar, Panruo Wu, and Yue Cheng. Wukong: a scalable and locality-enhanced framework for serverless parallel computing. In ACM SoCC 18