Quarkus 支持 AWS Lambda SnapStart

Quarkus 支持 AWS Lambda SnapStart

Amazon Web Services (AWS) 宣布了 AWS Lambda 的 SnapStart 功能。SnapStart for Java 能够减少在 AWS Lambda 上运行的 Java 函数的启动延迟,Quarkus 从第一天起就支持它!

Quarkus 是超音速亚原子 Java,专注于云原生应用。Quarkus 的核心理念一直是“在构建时完成传统框架在运行时做的事情”。Quarkus 针对低内存占用和快速启动时间进行了优化。Quarkus 为 Java 带来了开发者愉悦感,并使所有 Java 开发者都能利用他们的技能开发云原生应用,包括 AWS Lambda 工作负载。

Quarkus 使用 'quarkus-amazon-lambda' 扩展来构建和部署 Lambda 函数到 AWS Lambda。该扩展允许开发人员使用 Quarkus 的开发模型,如实时编码、持续测试等,并能够使用 CDI 注入和额外的 Quarkus 扩展。开发人员可以使用原生模式或 Java 模式将函数部署到 AWS Lambda。随着今天的公告,SnapStart 功能现已成为使用 Quarkus 编写的函数构建和部署到 AWS Lambda 的一个附加选项。

什么是 SnapStart?

通常,AWS Lambda 在首次调用新函数或为了处理流量而进行扩展时会创建一个新的执行环境。SnapStart 采取了不同的方法,它通过捕获已初始化的函数执行环境(内存和应用程序状态)的快照来实现。此外,它会持久化该快照并缓存起来,以便低延迟访问。当调用函数时,它不需要花费时间初始化代码、依赖项或框架。相反,Lambda 从持久化的快照中恢复新的执行环境。

SnapStart 注意事项

由于 SnapStart 通过快照工作并以低延迟恢复执行环境,这对 Quarkus 编写的函数非常有益。Quarkus 可以利用快照和预热代码路径来支持 Quarkus 所支持的库。

对于开发人员的代码和库,在使用 SnapStart 时需要考虑一些特殊情况:

网络资源连接:快照不能保证在函数恢复时与远程主机重新建立连接。开发人员需要确保并验证连接的状态。
将内存中数据从源拉取:通常,需要将数据从不同源拉取到内存中。如果源中的数据发生更改甚至过期,这也可能导致不一致。请确保并验证此类数据的一致性。
随机性:Lambda SnapStart 通过多次重用单个已初始化的快照来恢复执行环境,从而加速应用程序。因此,在初始化期间包含在快照中的唯一内容可能会在执行环境之间重复使用,从而可能不再保持唯一。请确保在初始化后生成唯一内容,并避免在初始化期间缓存唯一内容。有关唯一性和可供客户用于恢复唯一性的接口的更多考虑,请参阅功能文档。

Quarkus 的快速启动时间和与 SnapStart 的集成

典型的 Java 应用程序使用 JIT(即时)编译。应用程序启动时,需要一些时间让特定的预热代码路径运行得更好,这意味着需要额外的 CPU 周期用于预热。云原生应用程序需要更快的启动时间。提前(AOT)编译通过在构建时进行大部分优化来实现这一点。Quarkus 就是一个很好的例子。因此,我们从启动开始就获得了全速运行,并且在启动时没有编译的 CPU 开销。Quarkus 应用程序初始化有两个阶段:静态初始化和运行时初始化。这种区分遵循 GraalVM 原生编译的原则,将静态初始化内联到生成的执行文件中,而运行时初始化则在常规执行期间发生。我们比较了多个函数,以了解我们添加的每个功能的好处。

  • Hello 函数是一个简单的函数,它返回“Hello”并使用 Quarkus AWS Lambda 扩展。

  • Heroes 函数在 DynamoDB 之上实现了 CRUD 接口。它使用了 Quarkus AWS Lambda HTTP 和 RESTEasy Reactive。调用通过 AWS API Gateway。

对于每个函数,我们比较了:

  • 在没有 SnapStart 的情况下,调用持续时间、内存和计费时长。

  • 在预热阶段进行完全启动和类预加载的情况下,调用持续时间、内存和计费时长。

类预加载会加载和初始化应用程序使用的所有类。

结果

Hello 函数 无 SnapStart 有 SnapStart 原生

总时长

2230 毫秒

202 毫秒

-90.93%

356 毫秒

-84.05%

计费时长

131 毫秒

109 毫秒

-16.79%

356 毫秒

171.76%

内存

115 MB

104 MB

-9.57%

59 MB

-48.70%

Heroes 函数 无 SnapStart 有 SnapStart 原生

总时长

15728 毫秒

965 毫秒

-93.87%

1112 毫秒

-92.93%

计费时长

12550 毫秒

885 毫秒

-92.95%

1113 毫秒

-91.13%

内存

222 MB

173 MB

-22.07%

96 MB

-56.76%

Quarkus 与 AWS Lambda SnapStart 函数结合使用,能够实现接近原生性能的运行时优化,并且比常规 Java 快得多。对于某些函数,SnapStart 比 AWS Lambda 中的原生可执行文件冷启动更快。对于其他函数,原生镜像的内存使用率更高。

结论

开发人员现在有三种选项来构建和部署函数到 AWS Lambda:JVM 模式、原生模式,以及最新添加的 SnapStart 功能。这三种模式都有不同的用例。需要注意的是,SnapStart 仅是 AWS Lambda 的一项功能。

通过 SnapStart 功能,可以在 AWS Lambda 环境中使用 JVM 模式运行 Quarkus,其启动时间与原生镜像相似,在某些情况下甚至更快。为此,开发人员需要确保应用程序能够安全启动,例如,网络连接、资源等。幸运的是,如果您使用 Quarkus,其中许多方面已经为您处理好了。

通过将PR #29108 合并到 Quarkus 主分支,Quarkus 应用程序可以在 AWS Lambda 上使用 SnapStart 功能。该功能将作为实验性功能发布在 2.15 平台版本中。

如果您是 AWS Lambda 用户,我们鼓励您尝试使用或不使用 AWS Snapstart 来运行 Quarkus 并进行比较。请告诉我们您的结果和反馈。

有关更多技术细节,请访问 AWS Lambda SnapStart 博客,链接在此