首页 > Java > java教程 > Java 也可以无服务器:使用 GraalVM 实现快速冷启动

Java 也可以无服务器:使用 GraalVM 实现快速冷启动

Barbara Streisand
发布: 2025-01-07 06:16:44
原创
503 人浏览过

介绍

在使用无服务器代码时,一种相当常见的方法是将其编写为 Python、Node 或 Go 应用程序,因为它们以非常快的冷启动而闻名。

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

但是,如果我们面临针对 AWS Lambda 等无服务器环境的现有 Java 应用程序该怎么办?也许我们的大部分代码库都托管 Java,并且我们已经开发了一个丰富的工具和库生态系统,我们希望重用它们。将整个此类应用程序重写为不同的语言是昂贵的,更不用说,我们正在放弃静态类型安全和编译时优化等功能。

不久前,我遇到过这样的场景:9 个用 Java 编写的 AWS Lambda 应用程序在冷启动时会非常慢,甚至其中一些应用程序偶尔会超时。

相关 Lambda 被放置在 API Gateway 后面,并通过调用相应的 REST API 用于管理任务。此功能并未被广泛使用,因此遇到冷启动是不可避免的;然而,因为这不是一项关键服务,所以它是一个绝佳的实验机会:弄清楚这些 Lambda 是否可以被挽救。

不久之后,我就遇到了其他几篇关于开发人员成功使用 GraalVM 和 Quarkus 等框架来解决这个问题的博客文章。所以我决定亲自尝试一下。

但是这些工具到底是什么?

GraalVM

简而言之,GraalVM 是一个 Java 虚拟机,它附带了一个工具集,能够将 Java 编译为本机映像并使用 Graal JVM 执行它。

通常 Java 使用“即时”(JIT) 编译器,顾名思义,它在代码执行期间执行优化和编译。鉴于 JVM 优化器不断监视程序的执行并执行微调,随着时间的推移,可以转化为更好的性能,因此长时间运行的应用程序可以从中受益。

如果应用程序实例化一次,并且预计运行几个小时或更长时间,那么这很好,但如果我们正在处理 Kubernetes、AWS Lambda 和希望快速启动 Java 应用程序的批处理作业,执行对时间敏感的操作和规模取决于需求 - 对于汽车爱好者来说就是涡轮迟滞。

这就是 GraalVM 的 Native Image 功能可以提供帮助的地方。它没有使用 JIT 编译器,而是选择了一种非常不同的提前编译代码的方法 (AOT)。它使用静态代码分析来预烘焙我们的馅饼,甚至在构建期间预初始化某些类,以便它们在我们的应用程序代码执行时随时准备好触发。

结果呢?非常快的冷启动,这使得 Native Images 在应用程序生命周期短暂且必须快速启动的无服务器领域中非常有能力。

需要注意的一点是,尽管 GraalVM 具有 AOT 能力,但鉴于 GraalVM 用 Ja​​va 编写的新 JIT 编译器,它也可以作为现有 JVM 的直接替代品,提供更好的性能。

但是等等,还有更多!由于 Native Image 仅包含已知执行路径上的代码,因此我们会修剪多余的代码,并且所有未显式声明保留的 Java 类将不可用。因为我们只保留预期执行的位,所以我们提高了应用程序的安全性。

以臭名昭著的 Log4J 漏洞为例,该漏洞使用远程代码执行作为危害主机的手段。对于本机映像,小工具链接不太可能成功,因为传达攻击所需的库代码片段甚至无法访问。

夸库斯

Quarkus 另一方面,是一个针对无服务器应用程序进行优化的 Java 框架,它附带一个工具箱,通过提供专门配置和构建 AWS Lambda 作为本机可执行文件的扩展,使构建本机映像变得更加容易。

C1编译器

在 Lambda 优化之旅中,我还遇到了替代优化技术。其中一项优化是建议在 Lambda 执行期间独占使用 C1 编译器,这有望提供更快的冷启动。通常,在 JVM 内运行的 Java 应用程序使用分层编译,其中包括速度更快但不太优化的 C1,然后是速度较慢的 C2,但为长时间执行的 Java 应用程序提供更优化的性能。鉴于 Lambda 的寿命很短,C2 编译的好处可以忽略不计。

此处提供了逐步完成为 AWS Lambda 配置 C1 编译过程的指南。

当然,我想知道与我现有的 GraalVM 总体规划相比,该技术可以提供多少改进,因此我也将其包含在下面的研究结果中。

有关 JVM 分层编译以及 GraalVM 全新 JIT 编译器的更多详细信息,请参阅这篇 Baeldung 文章。

“但是等等,AWS SnapStart 怎么样?”

具有讽刺意味的是,在我将更改交付到生产环境几个月后,AWS 推出了他们最新的 SnapStart 功能,该功能可以拍摄正在运行的 Lambda 的快照,而不是重新初始化它,而是使用快照图像作为一个承诺更快冷启动的恢复点。我不得不尝试一下,看看使用 GraalVM 是否是浪费精力,并将其包含在我的发现中。

值得注意的是,为了充分利用 SnapStart,需要进行代码重构才能利用 beforeCheckpoint 和 afterRestore 挂钩(更多详细信息请参见此处)。鉴于我想尽可能避免任何重大代码更改,我“按原样”使用此功能,没有实现这些方法并重新排列任何代码。

总体规划

现在回到 GraalVM!令我惊讶的是,合并此解决方案后,除了添加和调整构建配置文件和一些必需的元数据之外,绝对不需要更改 Java 代码。

听起来好得令人难以置信?

也许有一点。鉴于我们使用的是 AOT 编译,在 Java 世界中,如果涉及到使用许多库所依赖的反射、代理、接口和服务注册表等语言功能,这会带来一定的挑战。这就是为什么 GraalVM 编译器需要声明额外的配置元数据来显式注册某些类和服务,以便它们可以包含在最终的工件中。 GraalVM 提供了一个所谓的代理,可用于与可执行文件一起运行,以自动识别所需的配置,从而使此过程变得更容易。

Quarkus 为知名库提供了几个扩展,使它们“原生图像友好”,但考虑到我正在使用现有的代码库,我的目标是避免任何重大重构(或与此相关的任何代码更改) ),我决定创建现有库所需的配置文件,以便成功生成原生映像。

请注意,编译 Native Images 是资源密集型的,与针对标准 JVM 运行时的字节码编译相比,它需要更长的时间。您可能会发现自己必须为构建节点分配更多 RAM 以避免内存不足问题,这不应该是一个大问题,但绝对是需要记住的事情。

现在我已经编译并打包了 Native Image Lambda,是时候将它们部署到测试环境中了。通常,Java Lambda 使用 AWS 的 Java 运行时来执行;然而,考虑到我们正在尝试使用原生映像,它是一个二进制工件,其中包含封装在 Graal JVM 中的应用程序代码,因此我们必须选择 AWS 提供的“自定义”Amazon Linux 环境之一。

测试方法

我使用 Postman API 集合向所有 9 个 Lambda 发送请求,并测量上述每种技术的冷启动响应时间。为了确保我总是遇到冷启动,我重新加载了目标 Lambda 的配置,以确保下一次调用不会使用可能已经热的实例。所有 Lambda 均配置有 1GB RAM。我还测量了每个配置的单次调用,因为该过程非常耗时;然而,观察到的响应时间描绘了一幅非常清晰的图景。

结果

所以有效果吗?绝对地!结果如下:

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

明显的赢家是:GraalVM Native Images - 平均而言,与未更改的 Java Lambda 相比,它的速度提高了 3 倍 - 不再有超时,并且响应时间更好,这正是我想要的实现。

如果不更改任何代码,SnapStart 的性能并不如我想象的那么好。当除了 SnapStart 功能之外还使用 C1 编译器时,它进一步降低了冷启动时间,但仍然没有击败 GraalVM 的 Native Image。这并不是说它不是一个可行的选择,因为它是一种快速且易于实施的改进。然而,如果我们想尽可能地优化 Lambda,并且我们有一些时间和资源来调整配置和构建过程,那么 GraalVM 在性能和安全性方面绝对更胜一筹。

内存占用

正如 GraalVM 所声称的那样,与常规 JVM 对应物相比,本机映像需要更少的资源才能有效运行。我想看看如果我要减少这些 Lambda 必须使用的 RAM 量,冷启动和热启动性能将如何保持。这次我只选择了一个 Lambda 应用程序来执行此测试。结果如下:

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

Java Can Be Serverless Too: Using GraalVM for Fast Cold Starts

他们兑现了他们的承诺!常规 JVM Lambda 在尝试配置 256 MB 或更低时会耗尽内存,而本机映像似乎未分阶段并继续执行。如果不是 128 MB 是最低的可用内存选项,我想知道我们还能低多少。原生映像不仅在冷启动时速度更快,而且在使用有限资源时提供一致的性能,这意味着更低的运营成本。

结论

Java 的生态系统丰富而庞大,每天都会出现许多新技术和增强功能,使 Java 在无服务器应用程序方面保持领先地位。 GraalVM 就是这样一种新兴技术。最初是一个研究项目,现在正在慢慢被采用,并成为标准 JVM(例如 HotSpot)的可行替代方案。在这篇博文中,我仅仅触及了 GraalVM 所提供功能的表面,我鼓励读者进一步探索它。 Adyen(文章链接)或 Facebook(文章链接)等公司有多个成功案例,他们能够利用 GraalVM 来节省时间和金钱。

因此,下次当您打算将 Java 作为一个选项打折时,请尝试一下 GraalVM。现在,Spring Boot 3 开箱即用地支持 GraalVM 本机映像,因此比以往任何时候都更容易将它们用于无服务器工作负载,以充分利用 GraalVM 提供的性能、低资源消耗和更高的安全性。

以上是Java 也可以无服务器:使用 GraalVM 实现快速冷启动的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板