1

华为云发布冷启动加速解决方案:助力Serverless计算速度提升90%+ - 华为云开发者联盟

 1 year ago
source link: https://www.cnblogs.com/huaweiyun/p/17072734.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
摘要:本文介绍了华为云对冷启动优化这一业界难题的探索之路,创新提出了基于进程级快照的优化方案。

作者信息——

子游:华为元戎高级工程师

平山:华为云中间件 Serverless 负责人

琪君:华为元戎负责人

Key Takeaways

  1. 冷启动 (Cold Start)一直是Serverless领域面临的优化难题之一,华为云创新提出了基于进程级快照的冷启动加速解决方案,致力于在用户几乎无感知的前提下,有效提升应用的冷启动性能;
  2. 特别的,Java应用冷启动速度慢的问题尤为突出。本文以Java场景为例,介绍华为云在冷启动性能优化方面的探索历程,并揭秘90%+性能提升背后的技术实现原理。文末我们也提供了Quick Start,帮助用户更快地上手该新特性。

一、问题引言:Java应用冷启动速度面临巨大挑战

Serverless应用启动时,都需要先进行初始化。其初始化时长一般取决于应用本身的属性,如业务逻辑、编程语言等,其中Java应用的初始化过程通常是最慢的。以下基于一个典型的Java应用,对其启动时延进行拆解,各阶段耗时分布如图1所示:

v2-68c7cc71e8ed3a8f5a9611f890c9f9a6_720w.webp

图1:Java应用启动耗时分解

其中,端到端冷启动耗时可分为2大部分:

  • 平台侧时间:

主要包含执行环境创建(如容器启动)、执行环境初始化(如代码包下载、部署)等准备工作,此阶段最多是秒级响应,在冷启动整体耗时中占比很低,通常不到5%,平台侧也支持一些优化方式,将耗时进一步压缩至毫秒级;

  • 服务侧时间:

主要包含应用框架启动(如构建Spring ApplicationContext)、业务初始化(如业务数据初始化)等动作,此阶段耗时一般较长。在本例中,应用框架启动耗时占比约30%,业务初始化占比约65%。由此推断,该阶段执行的动作是Java应用启动慢的核心所在

Java应用启动慢的根因其实也不难理解,主要有:

  • 框架复杂:Spring作为一个企业级的框架,为了支持广泛的应用需求,存在大量的可配置和初始化逻辑,并通过复杂的设计模式来支撑这种灵活性。例如,一个spring-boot-web的hello world,依赖的class文件就多达7404个,见图2;
  • JVM的一次编译,到处运行:类加载时,查找类、校验类的开销会随着应用复杂度而增长;同时,在应用刚启动时,方法还没有完全被JIT编译完成,因此大部分情况停留在解释执行,影响了应用启动的速度。
v2-150234cc8cfb169195506d40088fedfd_720w.webp

图2: hello world依赖的class个数

因此,对于时延敏感型的Java应用程序,在突发流量下发生冷启动时,可能会导致用户体验下降。为了应对这一挑战,用户可以提前预留资源来减少冷启动发生的频率,或者对自己的应用进行性能调优,但是第一类方案无形中增加了用户的keep-alive成本,第二类方案也有着较高的技术门槛且往往效果比较有限。

二、基于快照技术的冷启动加速:华为云的优化探索之路

Part I:站在巨人的肩膀上

业界针对Java应用的启动速度优化已有一些优秀的实践,可分为以下几类:

  • AOT:
    主要有GraalVM[1]、EJET等,AOT方案是通过在程序运行前,直接将Java源码编译成本地机器码,因为提前编译并不占用运行时间,以此来显著提升应用的启动速度,同时本地机器码可以持久化于磁盘中,不占用内存且可重复使用。但是该类方案在特定场景也存在一定的局限性,如GraalVM对反射的支持并不友好,在涉及反射的地方都需要新增配置;EJET虽然解决了反射的问题,但是其编译时间较长且不稳定,在复杂应用场景下也存在性能劣化问题。
  • AppCDS[2]:
    AppCDS方案是通过在JVM启动时从JSA文件读取共享数据,省略了共享类的加载过程,提升JVM启动速度;同时,多个JVM共享同一个归档文件,减少动态内存占用,可以提升内存使用率。该类方案主要适用于类加载比较多的场景,在一般场景下提升有限,且其对共享类的支持有一定限制,如运行时动态生成类不支持共享等。
  • 其他针对性(Spring框架)方案:

如Lazy Initialization[3]、Scanning-index[4]等,前者通过懒加载的方式来减少启动时加载类的数量,一定程度上提升启动速度;后者通过在编译阶段创建索引,避免启动时扫描所有路径来进行加速。但是该类方案在Serverless场景缺乏一定的普适性。

华为云FunctionGraph创新提出的基于进程级快照的冷启动加速解决方案,致力于在用户无感知(无需/少量进行代码适配)的前提下,帮助用户突破冷启动的性能瓶颈。本优化方案直接从应用初始化后的快照进行运行环境恢复,跳过复杂的框架、业务初始化阶段,从而显著降低Java应用的启动时延,实测性能提升达90%+。

Part II:快照方案如何优化Java应用启动速度

当用户Java函数打开冷启动加速的配置开关后,华为云FunctionGraph会预先执行函数对应的初始化代码,获取其初始化执行上下文环境的快照,并进行加密缓存。后续调用该函数并触发冷启动扩容时,会直接从提前初始化后的应用快照来恢复执行环境,而非重新走一遍初始化流程,以此达到极大提升启动性能的效果。

先结合图3直观对比一下优化前、后的冷启动流程差异:

v2-fd144ace48824cfdc12d159e1c64b09b_720w.webp

图3:基于快照加速的冷启动流程

基于快照的冷启动流程,主要包含以下几个关键步骤:

Step 1:平台侧提前准备执行环境,并预执行初始化代码、保存应用快照,此动作后续统称为Checkpoint

  • 与图1对应,此阶段一般占总耗时的90%左右。

Step 2:在请求到达,触发函数新实例扩容时,直接从应用快照来恢复新的执行环境,此动作后续统称为Restore

  • Restore 耗时是秒级,相当于将数十秒完整的初始化时间(在图 1 的示例中)缩短至秒级 Restore 耗时,启动性能提升了一个数量级。

Step 3:(可选)应用进程从快照恢复后,执行Restore Hook完成业务状态的刷新

  • 由于Image File是进程运行时的快照,在重建进程之后,会涉及到进程持有状态的有效性更新。例如已建立的外部链接、加载到进程里的缓存信息等。故我们引入了Restore Hook的概念,提供手段让业务对这些状态进行刷新,详见Part IV。

Step 4:应用Ready,具备接着往下执行业务逻辑的能力

特别的,容器本身也是主机上的进程,故本优化方案也支持容器粒度的Checkpoint,即对容器内指定进程进行CR,与传统的轻量化虚机快照相比,其精细化程度更高、也更灵活。其原理详见图4:

v2-1ca6bb40b6d36dfba2dcb615431107cd_720w.webp

图4:基于容器的CR流程

  1. 在Source机器上启动微服务,通过健康检查和初始化调用后,进行Checkpoint,停止服务,生成进程快照信息;
  2. 在Source机器上将进程快照信息和微服务所有相关依赖,进行压缩,加密生成内存快照包,并上传至云端存储。
  3. 在Target机器上从持久化存储中下载对应微服务的内存快照包,进行解压恢复。
  4. 在Target机器上Restore微服务进程;

Part III:快照技术揭秘

华为云提出的基于进程级快照的冷启动加速方案,其核心技术依托于CRIU[5],它支持对用户空间指定的进程进行“冻结”(即停止进程,并将该进程运行的所有上下文持久化为镜像文件),并在必要时对其进行“解冻”(即通过保存的镜像文件来正确恢复进程运行的上下文),其核心工作流程如图5-6所示[6]:

v2-8eb0aedc460fc2d4c4a2ff80eddc9a76_720w.webp

图5:CRIU如何工作——Checkpoint

v2-f8847972d75b1123409073d4462145bb_720w.webp

图6:CRIU如何工作——Restore

Checkpoint

    1. CRIU首先通过操作系统的 /proc 目录获取指定进程和该进程下所有子进程的信息,包含文件描述符(/proc/$pid/fd)、管道参数、网络配置和内存映射文件(/proc/$pid/maps)等;
    2. CRIU接着通过Linux 的ptrace syscall接口把一段特殊代码动态注入到该进程的地址空间,通过执行该动态代码,CRIU以UNIX守护进程的方式收集dumpee进程存放在寄存器里的内存数据;
    3. CRIU将所有进程信息都收集完毕后,再次调用ptrace接口,去掉动态注入的代码,恢复该进程的原有代码;
    4. CRIU根据收集的进程内存信息,生成多个以功能分类的镜像文件,并默认杀死进程,完成Checkpoint;

Restore

    1. CRIU解析Checkpoint阶段生成的镜像文件,并分析多进程的共享资源;
    2. CRIU通过Linux 的fork 接口重新构建、恢复进程和其共享资源;
    3. CRIU恢复所有任务的资源,但不包含内存映射地址,定时器,线程等;
    4. CRIU根据镜像文件重新映射内存空间,切换进程上下文,恢复进程的继续执行,完成Restore;

Part IV:Restore Hook

如Part II所述,虽然本优化方案能极大提升Java应用的冷启动速度,但是快照技术在某些场景也存在一定的局限性,较难做到对现有应用的全透明化。通过快照恢复后,应用的网络连接状态会受到影响,涉及到TCP Socket重连等场景,如服务注册、DB连接,分布式通信,消息队列等。

这部分场景依赖应用本身的网络重连机制来更新正确,因此,本优化方案中也引入了Restore Hook的概念,提供手段让业务对这些状态进行刷新。

Restore Hook当前已支持大部分主流第三方组件的重连,详见图7:

v2-d83b00a7f5e77c597e4b499c692e5568_720w.webp

图7:Restore Hook支持的第三方组件

不难发现,Restore Hook需要应用本身进行少量的代码适配。为了进一步简化应用的改造负担,我们也进行了一种新的技术尝试,可以理解其充当了用户应用与BaaS之间的纽带,通过状态卸载等手段,对开发者透明,帮助应用完成状态的自动化刷新。这部分探索会在后续的技术博文中跟大家分享,敬请期待。

三、效果实测:Java冷启动时延降低90%+

我们选取了公司内部典型的Java应用,对其原始初始化流程、Restore流程进行了对比测试,如图8所示。测试结果表明,本优化方案将应用的启动速度平均提升了95%+,即使快照包的增大一定程度上增加了包下载、解压的耗时,但最终端到端的冷启动时延也降低了90%+。

v2-0315ca4a6e56e26a80ab127d1ffd8b10_720w.webp

图8:冷启加速前后的数据对比

四、快速上手:基于华为云FunctionGraph的简单实战

华为云发布的基于进程级快照的冷启动加速方案,是一种性能优化服务,用户无需额外付费,只需进行简单的配置、少量的代码修改,即可享受到该创新方案带来的冷启动性能提升。

下文基于华为云FunctionGraph,为大家带来特性Quick Start

1、登录FunctionGraph控制台,创建Java函数,并打开“快照式冷启动”开关

v2-72fabf677fd537f3bbbffe71ef729b9d_720w.webp

2、(可选)配置Restore Hook,并在函数代码中实现对应的Hook逻辑

v2-7e5cb9fcde85cf1c2a2d51ada46cd482_720w.webp
v2-ca2f87c6d06f31cdd5fce6e6153a47c6_720w.webp

3、函数发布新版本后,触发快照的自动化制作

v2-e686f8be1855c45d9f3e61b09c49f802_720w.webp

4、请耐心等待快照制作完成(5min超时时间)

v2-0a7034760a3046737612d2a0357f289e_720w.webp
v2-3da0c4477db3fa2faa89ace49318f1ae_720w.webp

5、调用Java函数,体验快照优化后的性能提升

v2-e193ae2163ea98b1bdeb3953cedf21f7_720w.webp

五、总结与展望

本文介绍了华为云对冷启动优化这一业界难题的探索之路,创新提出了基于进程级快照的优化方案。当然,本方案也并非十全十美,它依然面临着一系列挑战,如文中提到的应用状态刷新、进程级CR的精细化控制、多平台的兼容性等,我们也在持续探索、优化中。

同时,FunctionGraph 作为华为元戎内核加持的下一代 Serverless 函数计算与编排服务,致力于持续为用户提供方便、迅捷的Serverless 服务体验。您可以登录华为云FunctionGraph控制台来深入体验,更多信息请参阅FunctionGraph官方文档[7]。后续我们将分享更多围绕通用全场景 Serverless的前沿理论及其案例实践,回馈社区。

[1]https://www.graalvm.org/22.3/reference-manual/java/compiler/

[2]https://wiki.openjdk.org/display/HotSpot/Application+Class+Data+Sharing+-+AppCDS

[3]https://spring.io/blog/2019/03/14/lazy-initialization-in-spring-boot-2-2

[4]https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-scanning-index

[5]https://github.com/checkpoint-restore/criu

[6]https://speakerdeck.com/udzura/introduction-to-criu?slide=32

[7]https://support.huaweicloud.com/functiongraph/index.html

点击关注,第一时间了解华为云新鲜技术~


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK