使用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技术的优点是兼容性最大程度的被保证,运行特性和我们平常的使用特性别无二致。

参考

相关推荐
Adolf_19931 小时前
Flask-JWT-Extended登录验证, 不用自定义
后端·python·flask
叫我:松哥1 小时前
基于Python flask的医院管理学院,医生能够增加/删除/修改/删除病人的数据信息,有可视化分析
javascript·后端·python·mysql·信息可视化·flask·bootstrap
海里真的有鱼1 小时前
Spring Boot 项目中整合 RabbitMQ,使用死信队列(Dead Letter Exchange, DLX)实现延迟队列功能
开发语言·后端·rabbitmq
工业甲酰苯胺2 小时前
Spring Boot 整合 MyBatis 的详细步骤(两种方式)
spring boot·后端·mybatis
新知图书2 小时前
Rust编程的作用域与所有权
开发语言·后端·rust
wn5313 小时前
【Go - 类型断言】
服务器·开发语言·后端·golang
希冀1233 小时前
【操作系统】1.2操作系统的发展与分类
后端
GoppViper4 小时前
golang学习笔记29——golang 中如何将 GitHub 最新提交的版本设置为 v1.0.0
笔记·git·后端·学习·golang·github·源代码管理
爱上语文5 小时前
Springboot的三层架构
java·开发语言·spring boot·后端·spring
serve the people5 小时前
springboot 单独新建一个文件实时写数据,当文件大于100M时按照日期时间做文件名进行归档
java·spring boot·后端