使用AWS Lambda SnapStart加速java项目启动速度[AWS Lambda教程-SAM系列]

我们知道在启动一个Java项目的时候普遍都比较慢,这是因为一个典型的java项目的启动会涉及到JVM启动、类路径组件扫描、类加载、对象创建和初始化、依赖注入、class字节码JIT编译等耗时环节,直到全部的工作就绪后才能对外服务。以一个SpringBoot项目为例,一般典型的启动时间在几十秒到数分钟不等。如果Java Spring项目在普通的Docker环境中运行,程序是长时间运行的,冷启动频次较低还可以接受;如果Spring项目在AWS Lambda中运行,程序可能会跟随请求压力动态不断的创建和销毁,冷启动的影响就比较大。

每个环境的生命周期包括三个主要阶段:InitInvokeShutdown。其中,Init 阶段引导函数的运行时,并运行函数的静态代码。在许多情况下,这些操作是在几毫秒内完成的,不会以任何明显的方式延长阶段。在其余情况下,出于多种原因,它们可能需要相当长的时间。首先,初始化某些语言的运行时可能很昂贵。例如,结合使用 Java 运行时和框架(如 Spring BootQuarkusMicronaut)的 Lambda 函数的 Init 阶段有时会长达 10 秒钟(这包括依赖注入、函数代码编译和类路径组件扫描)。其次,静态代码可能会下载一些机器学习模型,预先计算一些参考数据,或者与其他 AWS 服务建立网络连接。在为特定 Lambda 函数启用 Lambda SnapStart 后,发布该函数的新版本将触发优化过程。该过程会启动您的函数并运行整个 Init 阶段。然后,它获取内存和磁盘状态的不可变的加密快照,并缓存以供重用。随后调用该函数时,将根据需要以区块形式从缓存中检索状态,并用于填充执行环境。这种优化使调用时间更快且更具可预测性,因为创建全新的执行环境不再需要专用的 Init 阶段。

snapstart开启后,对Java程序的优化如下图:

  1. 预先进行程序的启动,完成初始化后立即创建一个snap保存下来供后续使用,这个过程相当于预热了程序的启动
  2. 如果有event触发lambda的执行,lambda会直接使用snap来恢复出现一个lambda instance,由于snap完成了最耗时的环节,恢复所需的时间相当于在程序预热的基础上快速的恢复运行。冷启动时间因此减少了。

关于SnapStart的更多细节可以看:Improving startup performance with Lambda SnapStart

在AWS SAM中完成Java SnapStart

使用AWS SAM为java程序开启SnapStart非常简单,只需要在template.yaml中完成如下的设置即可

java程序部署到lambda后,会马上被启动并创建snap快照,这个快照是被后续lambda instance冷启动使用的,snap快照也会被周期性的自动重新创建。

后续如果有事件触发lambda的执行,那么lambda insatance 会读取snap快照,立即恢复出就绪环境。

SnapStart和Graval的加速原理的区别

首先GraalVM最大的特点使用AOT(ahead-of-time)思想,可以把传统的java项目直接编译为GraalVM Native Image程序。通过将Java和基于Java字节码的应用编译为原生二进制可执行文件,这样用java和C/C++等编译型语言一样直接在OS上运行起来,无需JVM即可直接运行。Native Image二进制可执行文件支持近乎瞬时的启动,内存占用低,可零预热地达到峰值性能。GraalVM支持所有主要微服务框架,包括 Helidon、Micronaut、Quarkus 和 Spring Boot。

AWS Lambda SnapStart目前只能用在AWS Lambda无服务器函数计算平台,并且并不是AOT思想,而生快照思想。在提前完成类加载,对象创建和初始化等操作后,把当前的就绪状态打一个快照,实现就绪状态的冻结;后续需要按需启动时,直接用这个快照快速的还原出就绪状态,规避了启动过程中最耗时的缓解。恢复后程序还是在标准的JVM中,SnapStart技术的优点是兼容性最大程度的被保证,运行特性和我们平常的使用特性别无二致。

参考

相关推荐
2401_882727572 小时前
低代码配置式组态软件-BY组态
前端·后端·物联网·低代码·前端框架
追逐时光者3 小时前
.NET 在 Visual Studio 中的高效编程技巧集
后端·.net·visual studio
大梦百万秋4 小时前
Spring Boot实战:构建一个简单的RESTful API
spring boot·后端·restful
斌斌_____4 小时前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@4 小时前
Spring如何处理循环依赖
java·后端·spring
海绵波波1075 小时前
flask后端开发(1):第一个Flask项目
后端·python·flask
小奏技术6 小时前
RocketMQ结合源码告诉你消息量大为啥不需要手动压缩消息
后端·消息队列
AI人H哥会Java8 小时前
【Spring】控制反转(IoC)与依赖注入(DI)—IoC容器在系统中的位置
java·开发语言·spring boot·后端·spring
凡人的AI工具箱8 小时前
每天40分玩转Django:Django表单集
开发语言·数据库·后端·python·缓存·django
奔跑草-8 小时前
【数据库】SQL应该如何针对数据倾斜问题进行优化
数据库·后端·sql·ubuntu