从Java迁移到GraalVM启动快10倍


从 Java 迁移到 GraalVM Native,应用的启动时间从大约30秒缩短到大约3毫秒,更重要的是,内存使用量也从6.6 GB大幅减少到1 GB,而吞吐量和CPU利用率保持不变。

作为一次性电子邮件服务10MinuteMail的开发人员,我多年来一直在 Java 上运行该服务。我一直在关注新技术并拥抱新事物。  最近我决定不仅从 SpringBoot 2.x 升级到 3.x,还将应用程序从 Java 迁移到 GraalVM Native。

GraalVM是一种通用虚拟机,用于运行用 JavaScript、Python、Ruby 和 R 以及基于 JVM 的语言(如 Java、Scala、Kotlin 和 Groovy)编写的应用程序。GraalVM Native 是 GraalVM 的一项功能,允许将基于 JVM 的应用程序提前 (AOT) 编译为本机机器代码,从而缩短启动时间并降低内存使用量。

SpringBoot 3已将Spring Native项目合并到主要的Spring Boot流中,从而可以轻松开发与Native兼容的Spring应用程序。

我发现通过迁移到 GraalVM Native,我能够看到应用程序性能的显着改进。应用程序的启动时间从约 30 秒减少到约 3 毫秒,更重要的是,在吞吐量和 CPU 利用率相同的情况下,内存使用量也从 6.6 GB 显着减少到 1 GB。这使我能够减少硬件占用空间和成本,同时为网站用户提供相同水平的服务。

迁移过程中存在一些障碍。  部分原因是它实际上是同时完成的三个升级:

  • 从 SpringBoot 2.x 迁移到 3.x,
  • 从 Java 11 迁移到 Java 19,
  • 以及从 JVM 迁移到 Native 二进制文件。

我使用名为Thymeleaf的前端模板系统,并且还使用Thymeleaf 的第 3 方布局方言。不幸的是,由于使用动态 Groovy,布局方言不能作为本机可执行文件工作。  值得庆幸的是,我找到了该库的完整 Java 端口,解决了这个问题。

我还必须稍微改变一下处理配置的方式。  以前,我依靠 Spring Profiles 来管理本地、开发和生产环境所需的不同配置。对于 GraalVM Native 二进制文件,您无法以这种方式使用配置文件,因此我必须将环境特定配置提取到本地文件并在启动时引用该位置。

其他缺点之一是,虽然您可以在开发过程中通过在普通 JVM 中运行应用程序来快速构建和测试,但构建本机二进制文件要慢得多,作为 GitHub Action 大约需要 10 分钟(请参阅我关于使用 GitHub Actions 构建 Spring Boot 3 GraalVM Native本机镜像的文章),或者在我的笔记本电脑上需要 2 分 20秒。

我还失去了使用New Relic: Java APM 代理来监视和排除应用程序内的性能和错误的能力。

这些都是需要记住的事情。  然而,启动时间和内存使用的巨大改进使其非常值得权衡。 
这种类型的技术将允许更多基于 Java 的无服务器微服务和更快的自动扩展操作。

如果您的基于 Java 的应用程序遇到性能问题,特别是在无服务器架构的环境中,GraalVM Native 可能值得考虑作为解决方案。