作者 | Karsten Silz
译者 | 张卫滨
策划 | 丁晓昀
核心要点
Spring Framework 6.1 和 Spring Boot 3.2 支持 Java 21(Java 的最新 LTS 版本),而 Java 17 依然是基准版本。
虚拟线程的问世简化了并发编程并使其更加高效,而反应式编程和 Kotlin 协程也得到了改善。
检查点协调恢复 (Coordinated Restore at Checkpoint,CRaC) 是一种在 JIT JVM 中实现启动时间“缩容至零”的新方法,而基于现有的 GraalVM Native Image 支持实现“缩容至零”也大大提升了性能。
Spring Framework 6.2 和 Spring Boot 3.4 计划在 2024 年 11 月份发布,将支持 Jakarta EE 11,并与 Leyden 项目的 premain 优化保持一致,以加快启动速度。
Spring Boot 是构建新 Java 应用程序的流行框架,它将在 2024 年 4 月份迎来 10 周岁,而其基础 Spring Framework 则将提前一个月步入 20 岁。
Spring Framework 6.1(2023 年 11 月 16 日 发布)和 Spring Boot 3.2(2023 年 11 月 23 日 发布)支持运行在 Java 21 之上。这些版本将通过虚拟线程使并发编程更简单、更高效,并改进了反应式编程和 Kotlin 协程。为了缩短“缩容至零(Scale to Zero)”的启动时间,这两个版本对 OpenJDK 的检查点协调恢复(Coordinated Restore at Checkpoint,CRaC) 项目提供了初步支持,而现有的 GraalVM Native Image 支持也通过新发布的 GraalVM 版本得到了显著的性能提升。Spring Framework 6.2 和 Spring Boot 3.4 计划在 2024 年 11 月份发布,将支持即将发布的 Jakarta EE 11,并与 Leyden 项目的 premain 优化保持一致。
Spring 的新东家 Broadcom 在 2023 年 11 月 22 日,也就是 Spring Boot 3.2 发布的前一天,完成了对前东家 VMware 的收购。
Spring Framework 会在 2024 年 3 月份迎来 20 岁的生日,而 Spring Boot 也会在一个月后年满 10 周岁。
支持新的 LTS 版本 Java 21,但 Java 17 仍然是基线版本
Java 21 是当前的长期支持(LTS)版本,发布于 2023 年 9 月,与 Java 17-20 一样,它现在是运行时的一等公民。Java 21 最终确定了虚拟线程(参见下一节),改进了 Z 垃圾收集器,在 record 类型检查中使用记录模式(Record Pattern)使得代码更加紧凑,并使用模式匹配(Pattern Matching)简化了一些 switch 语句。甲骨文的 Java 布道师 Nicolai Parlog 在他的视频“从 Java 17 升级到 Java 21”中详细介绍了 Java 17 到 Java 21 的变化。
但是,Java 17(2021 年 9 月发布的 LTS 版本)依然是 Spring Boot 3 和 Spring Framework 6 的基线 JDK。这些版本在 2022 年 11 月增加了对 Jakarta EE 9 和 GraalVM Native Image 的支持,并通过带有跟踪和度量指标的 Micrometer 添加了嵌入式的可观测性。
预计 Spring Framework 6.x 和 Spring Boot 3.x 还将支持 Java 的下一个 LTS 版本 Java 25,该版本可能会在 2025 年 9 月发布。
提升效率的新方式:虚拟线程
虚拟线程简化了 Java 21 中的并发编程,是一种提高效率的新方法。应用程序不再需要配置线程池或使用回调,只需获取并使用虚拟线程即可。Java 会将每个虚拟线程挂载到一个平台线程上,即载体线程。当虚拟线程因输入 / 输出(I/O)而阻塞时,如数据库请求或 HTTP 调用,Java 会将载体线程用于另外一个虚拟线程。
这可以显著提高命令式、重 I/O 的 Java 应用程序的可扩展性,因为它们可以处理更多的并发请求。不过,CPU 密集型应用程序所获得的收益会比较少,因为卸载载体线程的机会更少。这同样适用于内存密集型的应用程序,因为 JVM 可用内存将会限制并发虚拟线程的数量。
甲骨文的 Java 语言架构师 Brian Goetz 这样指出,虚拟线程简化了编程,因为它“为我们提供了很多我们每天都认为理所应当的事情,比如顺序控制流、局部变量、异常处理、单步调试和剖析”。
当在synchronized
Java 代码片段中进行 I/O 操作或使用锁时,虚拟线程就失去了效率优势,载体线程会被阻塞,也就是所谓的线程锚定(thread pinning)。多个 JDBC 驱动都表现出了这种行为。Spring 生态系统中的库也可能锚定虚拟线程,一些 Java 库同样如此。
Spring Boot 3.2 可以通过在 Java 21 上运行并将spring.threads.virtual.enabled
属性设置为true
来启用虚拟线程。Tomcat 和 Jetty 将使用虚拟线程,applicationTaskExecutor
和taskScheduler
bean、Kafka 和 RabbitMQ 的监听器、新的 HTTPRestClient
以及 Spring 生态系统的许多其他组成部分也将使用虚拟线程。
虚拟线程处理的是单个任务,而 Java 中的结构化并发则简化了这些任务的协调。Java 21 中的这一预览特性需要更多的时间来完善,该特性可能会采取不同寻常的交付措施,也就是在 Java 22 中以保持不变的形式再次发布 Java 21 中的功能,以获取更多的反馈。
提高效率的既有方法:反应式编程和 Kotlin 协程
反应式编程是扩展 Java 的另一种方式,Spring Framework 从 2017 年 9 月份的第 5 版开始就支持它。与使用虚拟线程相比,反应式编程更为复杂,因为管理回调和调试更具挑战性。这可能就是 2021 年 8 月份 Goetz 预言“Loom 将扼杀反应式编程”的原因。
这是一个有争议的言论,因为 Loom 项目“并没有解决反应式编程所支持的其他一些特性,即背压(backpressure)、变更传播以及可组合性。[……] 毕竟,它只是创建线程的一种不同方式而已”,monday.com 的高级工程技术负责人 Tomasz Nurkiewicz 这样认为。
Broadcom 似乎认可 Nurkiewicz 的观点,因为它改进了对反应式编程的支持。例如,它在缓存和调度中增加了反应式支持。
Spring Framework 还改进了对 Kotlin 协程的支持,自 2018 年以来,协程简化了异步任务的协调。协程与 Java 即将推出的结构化并发(Java 22 中的预览特性)具有相同的目标。在 Spring Framework 6.1 中,Kotlin 协程可以使用面向切面编程(AOP)。它们还可以使用虚拟线程来提高效率。
缩容至零的新方法:CRaC
Broadcom 在“Runtime efficiency”主题下支持了 OpenJDK 的 CRaC 项目。该倡议的优势包括更便宜的托管服务、可持续的计算并且能够使 JVM 成为 Kubernetes 中的好公民。CRaC 是 Spring 应用程序以亚秒(sub-second)级启动时间“缩容至零”的新方法。
“缩容至零”意味着除非有请求传入,否则不会运行任何应用程序实例。这样可以节省处理成本,但是需要近乎瞬时的应用程序启动。传统的 Java 应用程序启动速度太慢,无法实现这种“缩容至零”。
Spring Framework 6.1 和 Spring Boot 3.2 提供了对 CRaC 的初始支持,这大大缩短了 Java 应用程序的启动时间,并降低了其达到峰值性能的时间。用户在运行的 Java 应用程序中触发一个检查点。然后,CRaC 会将应用程序的快照写入磁盘。该快照可以在以后运行应用程序的时候进行恢复。
Broadcom 的软件工程师兼 Spring Framework 的核心提交者 Sébastien Deleuze 于 2023 年 10 月 4 日的 Devoxx Belgium 大会上分享了对 Spring PetClinic 应用程序使用 CRaC 的结果。在 Azure 1 CPU 2 GB RAM 云服务器上,启动时间从 11.97 秒缩短到了 210 毫秒,快了 56 倍。在 zure 2 CPU 4 GB RAM 云服务器上,启动时间从 5.76 秒变为 130 毫秒,快了 44 倍。
Broadcom 通过将获取快照及其恢复映射到现有的 Spring Bean 生命周期阶段,添加了对 CRaC 的支持;检查点会映射为 Spring 应用上下文的完全停止,而恢复映射为它的重启。Broadcom 借此机会重新审视了 Spring 的生命周期模型,该模型是 Spring 3.0 在 2019 年引入的。实现生命周期的组件会自动参与 CRaC 的检查点和恢复。Spring 还将现有的组件移入生命周期,如任务调度器、连接池和其他持有资源的组件。Spring 应用上下文将支持多次的、顺序的停止和重启。
Spring 之所以需要这些变更是因为 CRaC 要求所有文件、套接字和池在检查点关闭,并在快照恢复后重新打开。应用程序及其所有的库必须要支持这一点,否则检查点将会失败。
除了关闭和重新打开资源,CRaC 还有更多需要权衡的地方。首先,它只能在 Linux 上运行,因为它依赖于 Linux 的用户空间的检查点和恢复(Checkpoint Restore in Userspace,CRIU) 特性。在生产环境中,这是一个无关紧要的考量因素,因为大多数的 Java 应用程序已经在 Linux 上运行。但是,开发人员在 Windows 和 macOS 上进行开发时,必须使用 Linux 容器进行测试。
CRaC 还需要 JDK 的支持。Azul 目前提供了这样的 JDK,包括免费的 OpenJDK 发行版“Azul Platform Core”和商业发行版“Azul Prime”。尽管 Azul 的副 CTO Simon Ritter 在 2023 年 6 月表示,他“目前还不知道有任何其他发行版计划支持 CRaC”,但是 Bellsoft 的 Liberica OpenJDK 发行版在 2023 年 12 月为 Java 17 和 21 添加了对 CRaC 的支持。Goetz 还在 Devoxx Belgium 上讨论了 CRaC:“我认为 CRaC 是一个很好的探索 [……] 但是,作为一种编程模型,我并不看好它。[……]CRaC 试图以牺牲正确性为代价来加快运行速度,我不喜欢这种权衡。”
在 CRaC 中,应用程序在获取快照前必须先运行。理想情况下,应用程序必须在“预热状态”下运行,并具有类似生产环境的负载。这可以在 CD/CI 流水线中,也可以在生产环境中实现。
最后,应用程序的秘密信息,如数据库凭证或 API 秘钥可能会在快照文件中泄露。对快照文件进行加密可以解决这一问题,但代价是写入和读取快照文件时,CPU 的负载会比较高。Broadcom 计划在 Spring Framework 中添加恢复后更新配置的功能。例如,通过应用上下文刷新(Application Context Refresh) 恢复快照后,可以将快照文件中的假数据库凭证替换成真的数据库凭证。
对 CRaC 的支持是“初步性的”,因为 Broadcom 计划对其进行进一步的改进,而且某些库需要更新才能关闭和重新打开资源。Broadcom 拥有一个包含 Spring 项目和 CRaC 的仓库,用来进行单元测试和应用测试。它的状态文件 展示了哪些项目通过了,哪些项目失败了。
Spring 文档中包含了关于 CRaC 的更多信息。
实现缩容至零的既有方法:GraalVM Native Image
Spring 6 和 Spring Boot 3 已经有了一种缩容至零的方法,也就是 GraalVM Native Image,这是一种预先(Ahead-of-Time,AOT)编译器,可以为 Linux、Windows 和 macOS 创建原生可执行文件。与 CRaC 类似,它能将启动时间缩短到接近为零。与 CRaC 不同的是,它还能显著降低内存使用率,提高安全性并缩小应用程序文件的大小。
在 Azure 1 CPU 2 GB RAM 云服务器上,使用 GraalVM Native Image 的 Spring PetClinic 的启动时间从 11.97 秒缩短到了 200 毫秒,比 CRaC 还要快 10 秒。在 Azure 2 CPU 4 GB RAM 云服务器上,启动时间从 5.76 秒变成了 210 毫秒,比 CRaC 慢了 80 毫秒。
Deleuze 介绍了在 Spring PetClinic 中使用 GraalVM Native Image 所节省的内存。启动后,JIT JVM 的内存消耗为 214MB,CRaC 为 204MB。GraalVM 社区版将内存消耗降低到了 82GM,比 JVM 方式降低了 2.6 倍。Oracle GraalVM(以前的企业版)达到了 61MB,比 JVM 方式降低了 3.5 倍。
将 GraalVM 应用程序的峰值性能与 JVM 和 JIT 进行对比是一个有争议性的话题。在 2023 年 11 月 2 日的“A Bootiful Podcast”中,Broadcom 的 Spring 开发人员倡导者 Josh Long 采访了 GraalVM 的创始人兼甲骨文的副总裁 Thomas Wuerthinger。Wuerthinger 说,“上一次(Oracle GraalVM)发布的重大新闻是,我们首次在包括峰值吞吐量在内的所有方面击败了 JIT 编译器”(从 34 分 56 秒开始)。一周后,Ritter 在同一个 podcast 中指出,“使用 GraalVM 编译的代码和静态编译的代码所获得的最终性能水平,与使用 JIT 编译的代码所获得性能水平是不一样的”(从 39 分 6 秒开始)。
GraalVM 团队为 21 版本针对 Spring PetClinic 测试了性能。他们发现,Oracle GraalVM 的峰值吞吐量比使用 JIT 编译器的 JVM 高出了 8%,分别是 11902 请求 / 秒和 11066 请求 / 秒。
Deleuze 对同一个应用程序进行了测量。从技术上讲,他也发现 GraalVM 优于 JVM,但是领先的幅度是 6%,分别是 1363 请求 / 秒和 1283 请求 / 秒。但是,Oracle GraalVM 从这个值开始下降,一直到了 1190 请求 / 秒,而 JIT JVM 的性能则稳步上升,在大约 33 秒之后超过了 Oracle GraalVM,最终达到了 1283 请求 / 秒,而且仍在不断增长。Deleuze 没有使用 Oracle GraalVM 的性能引导优化(Performance-Guided Optimization,PGO),所以性能有所下降。
GraalVM 社区版从 992 请求 / 秒开始,最终达到了 1008 请求 / 秒,两者的差别不大。CRaC 在 60 秒的基准测试中胜出,从 896 请求 / 秒开始,到 1500 请求 / 秒结束。目前,没有超过 60 秒范围的数据。
与 CRaC 类似,使用 GraalVM Native Image 也有一定的权衡。有些 Java 特性是无法实现的(比如,在运行时加载任意的类,或者创建新的类或方法),有些特性则是不完整的(如 macOS 上缺少对 AWT/Java FX 的支持或者 Java Flight Recorder 事件的数量有限)。并非所有的可观测性和测试框架都支持 GraalVM,因为 GraalVM 不允许在运行时生成动态代码,也不能运行 Java 代理。反射和类加载是可能实现的,但是需要进行配置。
所有的这些都会破坏 Spring 项目或第三方库。与 CRaC 一样,Broadcom 有一个针对 Spring 项目和 GraalVM Native Image 的测试仓库。社区驱动的 GraalVM 可达性元数据仓库(GraalVM Reachability Metadata Repository) 包含流行库的 GraalVM Native Image 配置。在 Spring 中使用时,GraalVM 原生镜像会自动查询该仓库。
最后,GraalVM 的开发体验比 JIT Java 差。正如 Deleuze 在演讲中所言,构建时间是“几分钟而不是几秒钟”,在 Windows 和 macOS 上调试 GraalVM 应用程序需要在 Linux 容器中编译和运行应用程序,这会非常耗时。Java 开发人员在开发过程中主要使用 JIT JVM,并使用 GraalVM Native Image 构建 CI/CD 流水线。但在添加新库或解决生产环境的问题时,他们必须在自己的 PC 上使用 GraalVM Native Image。
更快的 JIT JVM 启动速度:Spring AOT 和类数据共享(Class Data Sharing,CDS)
Spring AOT 是负责将 GraalVM Native Image 集成到 Spring 中的项目。在没有 GraalVM Native Image 的 JIT JVM 上运行时,也可以使用其中的一些优化特性。Broadcom 估计这可以将启动时间缩短约 15%。Spring 的文档中有详细的描述。
OpenJDK JVM 会在每次启动时计算可用类及其成员的列表。OpenJDK 的 CDS 特性会将这些信息保存在一个文件中,并在以后运行时进行加载。这也能将启动时间缩短约 15%。Spring Framework 6.1.1 通过一个特殊的 JVM 标记支持该特性。Spring Boot 目前还不支持该功能,但是未来可能会提供支持(请参见这里和这里)。
Deleuze 撰写了一篇关于 Spring 和 Spring AOT 中 CDS 的深入介绍。他测量了在 Spring PetClinic 中组合使用 Spring AOT 和 CDS 所缩短的启动时间。在 Azure 1 CPU 2 GB RAM 云服务器上,这种组合比从可执行 JAR 启动节省了 50% 的时间,比从通过解压后的类启动节省了 37% 的时间。在 zure 2 CPU 4 GB RAM 云服务器上,分别节省了 53% 和 39%。他强调说,“Spring 应用程序的生产部署应该将其解压拆包,以获得最佳的启动时间。”
其他特性以及 Spring 的未来
更新后的 HTTP REST Client 将 Spring 反应式编程中的流畅接口和虚拟线程的使用结合了起来:
RestClient client = RestClient.create(baseUrl);
ResponseEntity person = client.get().uri("/persons/1")
.accept(MediaType.APPLICATION JSON)
.retrieve( )
.toEntity(Person.class);
JDBC Client API 现在也有了流畅接口:
JdbcClient client = JdbcClient.create(dataSource);
Optional person = client.sql("SELECT .. WHERE ID = :id")
.param("id", 3)
.query(Person.class)
.optional();
数据绑定和校验也通过更多的一致性得到了改善,例如内置的 Spring MVC 处理器方法校验以及对 Java record 的扩展支持。Spring Boot 3.2 将获得为其一年的免费支持,直到 2024 年 11 月 23 日。商业支持将会再增加 15 个月,直到 2026 年 2 月 23 日。自 2018 年 3 月的 Spring Boot 2.0 以来,这些支持的时限模式都是一直存在的。只有 Spring Boot 2.7 作为最后一个 2.x 版本,获得了额外 6 个月的免费和商业支持,对免费支持也随着 Spring Boot 3.2 的发布而结束,对 2.7 的商业支持将持续到 2025 年 8 月 24 日。
Spring Boot 3.2 移除了 Spring Boot 3.0 废弃的类、方法和属性。Spring Boot 3.2 还更新了很多依赖项,比如 Spring Security 6.2、Kotlin 1.9、Hibernate 6.3 和 Kafka 4.6。Spring Boot 3.2 和 Spring Framework 6.1 的发布说明全面描述了所有变更。
Spring Framework 6.2 预计会在 2024 年 11 月份发布,将支持 Jakarta EE 11。该版本将会包含更新的 API,比如 Jakarta Servlet 6.1 和 Jakarta Persistence 3.2。在使用 Spring 的高层级抽象时,比如@RestController
或 Spring Data,这些依赖项的更新大多是不可见的。
Spring 还宣布与 Leyden 项目合作,开展一个名为“premain 优化”的项目。按照 Deleuze 所言,这些优化是“CDS + AOT 缓存的组合”。它目前还处于早期阶段,但是 Broadcom 预计启动时间将会快 2 到 4 倍,而且几乎不会产生任何取舍。
对 Sébastien Deleuze、Oliver Drotbohm 和 Mark Paluch 的采访。
Broadcom 的 Spring Framework 核心提交者 Sébastien Deleuze、Broadcom 的 Staff 2 工程师 Oliver Drotbohm 以及 Spring Data 项目的负责人 Mark Paluch 回答了 InfoQ 的一些问题。
InfoQ:借助 Java 17 和 Jakarta EE 9,Spring Boot 3.0 提供了很多的特性,但是它的迁移可能会比较耗时。到目前为止,它的采用情况如何呢?
Oliver Drotbohm:Spring Boot 3 和 Spring Framework 6 的反响非常好。我们看到,很多企业升级到了这些版本,一方面是为了基础设施的更新,另一方面也是为了它们的新特性,如对 GraalVM 的支持和开发服务。尽管如此,根据对 JakartaEE API 的依赖程度,包名称的更改可能会使这次的升级比以往的版本更具挑战性。通过 Spring Boot Migrator 以及基于 OpenRewrite 的工具中对升级的支持,我们在努力帮助社区减少这种工作量。2.7 版本的生命周期已终结(EOL),但幸运的是,Broadcom 提供了延长至 2025 年 8 月份的商业支持服务。
InfoQ:Spring 生态系统中一些组成部分花了很长一段时间才支持 Spring Boot 3.0,比如 Spring Cloud AWS 就花费了五个月。您对 Spring Boot 3.2 得到支持的速度有何预期?
Sébastien Deleuze:Spring Cloud AWS 是一个社区运营的项目,所以 Spring 不能代表他们发言。但我们预计,与主版本升级相比,从 Spring Boot 3.0 升级到后续的 3.x 小版本会更快、更顺利。Spring 团队负责的 Spring Cloud 项目 在 2023 年 12 月 6 日 就使用了 Spring Boot 3.2。
InfoQ:Spring Boot 3.0 内置了对 GraalVM Native Image 的支持。作为 Spring 开发人员,我该如何知道我的应用程序是否能与 GraalVM Native Image 协同使用?毕竟,不是所有的库都是开箱即用的。
Deleuze:作为 Spring 开发人员,你可以在 Spring AOT 冒烟测试状态页面大致了解哪些生态系统中哪些组成部分已经通过了测试,并且可以与 GraalVM Native Image 兼容。我们将继续在每个补丁版本中完善原生支持,我们看到,Spring 方面的兼容性问题报告越来越少。对于开源库,Spring Boot 的设计是利用 GraalVM 的可达性元数据,你可以在这里找到已支持的库的列表,该列表的增长速度非常快。使用反射、代理或资源的非开源库可能需要自定义 hints。
InfoQ:假设开发人员发现了无法与 GraalVM Native Image 协同使用的库,那么他们是否应该通过为该库创建 GraalVM Native Image 配置 hints 来解决这个问题呢?
Deleuze: 是的。对于开源的库,最简单的方法可能是将这些 hints 信息贡献给 GraalVM 可达性元数据仓库,因为它提供了所有的指南和原生测试基础设施。 如果这不是一个开源的库,或者开源库想提供内置的原生支持,开发人员可以以 JSON 文件的形式提供 GraalVM 可达性元数据 ,可以直接将其放到库的 JAR 文件中。 基于 Spring 的库还可以使用更强大的动态运行时 hints 生成功能(Spring 套件使用了相同的方式来提供原生支持),参见 Spring Framework 相关的文档 。
InfoQ:CRaC 是 Spring Boot 3.2 中的一项重要特性。如果存在已打开的文件或套接字,获取 CRaC 快照将会失败。作为 Spring 开发人员,我如何知道应用程序中的库是否能够可以与 CRaC 协同使用?
Deleuze:我们有专门针对 CRaC 支持的冒烟测试,你可以在这个状态页面上大致了解 Spring 为处理资源生命周期所提供的开箱即用支持的范围。作为 Spring 开发人员,可以按照相关的 Spring Framework 文档实现自定义的 Spring 生命周期管理,或者直接使用 org.crac API 为 CRaC 处理应用程序端的资源生命周期管理。
InfoQ:虚拟线程是 Spring Boot 3.2 的第二个重要特性。但是,当在synchronized
Java 代码片段中执行 I/O 操作或使用锁的话,它们就失去了这种优势,也就是所谓的线程锚定(thread pinning)。JDBC 驱动很容易出现这种行为。我该如何知道应用程序的库是否会锚定虚拟线程呢?
Mark Paluch:很多流行的 JDBC 驱动从很早就开始为 Loom 做准备了。Oracle 和 Postgres 就是其中的两个早期采用者。除此之外,我们知道微软(SQL Server)和 MySQL 也在努力使它们的驱动很好地适应虚拟线程。 否则的话,要想知道你的 JDBC 驱动表现如何,以及是否会遇到内核线程锚定几乎是不可能的。最初的 JEP 444 引入了通过设置-Djdk.tracePinnedThreads=full系统变量或使用 Java Flight Recorder 来探测平台线程锚定事件的方法。 在开发过程中,你可以使用 Loom-Unit 来探测线程锚定,它是 JUnit 5 的一个开源扩展。 除了 JDBC,与消息代理或其他外部系统的交互也可能需要仔细检查。如果它们使用了原生库(JNI),将会停留在载体线程上,这可能很难被发现。我们强烈建议测试你的应用程序,研究它在虚拟线程上的表现,以尽早发现潜在的问题。
InfoQ:在 2023 年 10 月 4 日的 Devoxx Belgium 演讲中,你分享了PetClinic 的吞吐量数据。Oracle GraalVM 开始表现非常强劲,后来有所下降。JIT JVM 一开始比较弱,但是后来持续增长并超过了 Oracle GraalVM。在你幻灯片显示的 60 秒之后,这两种方案的表现如何?
Deleuze:我没有具体的数据可以分享。不过,我们通常可以看到,在不使用配置文件引导优化(Profile-Guided Optimization,PGO)的情况下,Oracle GraalVM 会比完全预热的 JVM 稍慢一些(我认为数值是百分之几)。有了 PGO 之后,速度就差不多了。
InfoQ:OpenJDKjlink
工具可以减少部署文件的大小。在部署 Spring Boot 3.2 应用程序的时候,可以使用它吗?
Deleuze:Spring 团队对减少部署文件的大小很感兴趣,但是在这方面最佳的技术方案尚不明确。 jlink可以用于这一目的,但是它有各种限制,可能会妨碍它的广泛应用。我们期待 Leyden 项目能否以及如何解决这一问题。考虑到这仍是一个不断发展的技术领域,而且大多数云供应商都支持容器镜像缓存,我们可能会在短期内将重点放在使用 Spring 提高运行时效率的其他领域。
关于作者
Karsten Silz,Karsten Silz 是全栈 Java 开发人员(Spring Boot、Angular 和 Flutter),在欧洲和美国工作了 25 年。2004 年,他在美国合伙创立了一家提供软件产品的初创公司。Karsten 领导了 13 年的产品开发,并在公司成功出售后离开。自 2003 年以来,他还一直以承包商的身份工作。2020 年,他作为 CTO 共同创立了 SaaS 初创公司“Your Home in Good Hands”。
查看英文原文:
Spring Boot 3.2 and Spring Framework 6.1 Add Java 21, Virtual Threads, and CRaC (https://www.infoq.com/articles/spring-boot-3-2-spring-6-1/)
声明:本文为 InfoQ 翻译,未经许可禁止转载。
热门跟贴