Spring 官宣,要干掉原生 JVM!

原文:spring.io/blog/2021/03/11/announcing-spring-native-beta

Spring 团队日前发布了 Spring Native Beta 版。通过 Spring Native,Spring 应用将有机会与 GraalVM 原生镜像的方式运行。为了更好地支持原生运行,Spring Native 提供了 Maven 和 Gradle 插件,并且提供了优化原生配置的注解。

Spring 发布了 Spring Native 的 beta 版本,并在http://start.spring.io上运行它。

实际上,这意味着自 Spring 成立以来,除了 Spring 支持的常规 Java 虚拟机之外,我们还将添加 Beta 支持,以使用 GraalVM 将 Spring 应用程序编译到本机映像中,从而提供一种部署 Spring 应用程序的新方法。支持 Java 和 Kotlin。

这些本机 Spring 应用程序可以部署为独立的可执行文件(无需安装 JVM),并提供有趣的特性,包括几乎即时启动(通常<100ms),即时峰值性能和较低的内存消耗,但所需的构建时间和运行时优化次数少于 JVM。

Spring 官宣,要干掉原生 JVM!_第1张图片


使用简单mvn spring-boot:build-imagegradle bootBuildImage命令,您可以生成一个优化的容器映像,该映像将包含一个最小的 OS 层和一个小的本机可执行文件,该映像仅随附 JDK,Spring 以及您在应用程序中使用的依赖项中的必需位。请参阅下面的示例,其中包含 50MB 可执行文件的最小容器映像,其中包含 Spring Boot,Spring MVC,Jackson,Tomcat,JDK 和应用程序。

Spring 官宣,要干掉原生 JVM!_第2张图片 图片

这种原生方式,在很多场景下都会对 Spring 应用产生价值:

  • 具有 Spring Cloud 功能的无服务器

  • 以更便宜和更可持续的方式托管 Spring 微服务

  • 非常适合 VMware Tanzu 等 Kubernetes 平台

  • 想要创建最佳的容器映像来打包您的 Spring 应用程序和服务

在使用场景上,比如 Piotr Mińkowski 提供了一个非常棒的指南,介绍了如何在 Knative 上使用 Spring Boot 和 GraalVM 构建原生微服务。

1. 团队协作

Spring Native beta 是整个 Spring 团队及其家族项目广泛合作的结果:Spring Framework、Spring Boot 还包括 Spring Data、Spring Security、Spring Cloud 和 Spring Initializr。

据悉,原生功能的工作范围比 Spring 更广,因为原生涉及到更广泛的 JVM 生态系统,所以官方一直在与 GraalVM 团队合作,以改善原生镜像的兼容性和资源消耗。

以下是来自 GraalVM 团队的 Vojin Jovanovic 的一段话。

“与 Spring 团队协作打造原生 JVM 生态系统是一件非常愉快的事情:他们深厚的技术知识,再加上对社区的敏感触觉,总是能带来最好的解决方案。最新的 Spring Native 版本,以及它在 JVM 生态系统中的众多用法,为原生编译的广泛采用铺平了道路。”

2.支持范围

随着 Spring Native 从 alpha 过渡到 beta,我认为弄清我们提供的支持范围很重要。

Alpha 是第一步,我们进行了大量试验并完善了 Spring Native(以前称为 Spring GraalVM Native)的体系结构,兼容性和对一系列样本进行了重大更改的封装。我们还报告了 GraalVM 团队修复的许多问题,目的是缩小 JVM 与 Spring 应用程序的本机之间的差距。

虽然仍被认为是实验性的,但 beta 意味着 Spring 现在为 Spring 生态系统的子集提供了对 native 的支持。如果项目正在使用受支持的依赖项,则可以在项目上进行尝试;如果出现问题,则引发错误或提出请求请求。最新版本的 Spring Boot 2.x 次要版本的每个修补程序版本都会出现一个新版本的 Spring Native。Spring Native 0.9.0 支持 Spring Boot 2.4.3,Spring Native 0.9.1 支持 Spring Boot 2.4.4,等等。虽然会发生一些重大变化,但我们将记录迁移路径。文档质量达到了一个新的水平:参考文档以 html 单页或 pdf 的形式提供],并且我们发布了本机提示的 Javadoc 公共 API。

3.start.spring.io

Stéphane Nicoll 在对 http://start.spring.io 和相关 IDE 的集成中,引入了对 Spring Native 的支持,所以现在这是探索如何使用 Spring 构建原生应用最简单的方式。

Spring 官宣,要干掉原生 JVM!_第3张图片


添加 Spring Native 依赖后将会使用所需的依赖和插件自动配置 Maven 或 Gradle 项目,以便于支持原生。应用代码本身没有变化。

请检查自动生成的 HELP.md 文件,该文件包含了有用的链接和文档,同时它还能标记出来你是否选择了一些在原生环境下不支持的依赖。

4. 提前转换

本机不同于 JVM:类路径在构建时是固定的,例如需要反射或资源进行配置,没有类延迟加载(可执行文件中附带的所有内容在启动时都加载到内存中),并且可以调用一些代码在构建时。

为了充分体现这些特性并允许 Spring 应用程序在本机上以最大的兼容性和最小的占用空间运行,Brian Clozel 在此版本中引入了 Spring 提前(AOT)Maven 和 Gradle 插件,它们可以提前执行您的应用程序上的转换。

第一种转换旨在基于由惊人的 Andy Clement 设计和实现的推理引擎来生成 GraalVM 本机配置(反射,资源,代理,本机映像选项),该引擎了解什么是 Spring 编程模型和基础架构。例如,对于每个由注释的类@Controller,一个条目将被添加到生成的reflect-config.json文件中。

无法推断出某些本机配置,对于这些情况,我们引入了本机提示注释(有关更多详细信息,请参见 Javadoc),这使 Spring Native 可以比基于常规 JSON 的本机图像配置更可维护,类型安全和灵活地支持本机配置。例如同春本地 MySQL 驱动支持提供线索,让一代机映像正确的条目reflect-config.jsonresource-config.json以及native-image.properties如下:

@NativeHint(
    trigger = Driver.class,
    options = "--enable-all-security-services",
    types = @TypeHint(types = {
       FailoverConnectionUrl.class,
       FailoverDnsSrvConnectionUrl.class,
       // ...
    }), resources = {
    @ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),
    @ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",
                      isBundle = true)
})
public class MySqlHints implements NativeConfiguration {}

NativeConfiguration和其他动态配置机制允许更强大的和动态的配置生成,但要注意它们的 API 将在即将到来的版本演变了很多。

Spring 开发人员还可以使用特定于应用程序的本机提示直接注释其@Configuration@SpringBootApplication类,例如,Book通过诸如RestTemplate或的编程 API 将类序列化为 JSON WebClient

@TypeHint(types = Book.class)
@SpringBootApplication
public class WebClientApplication {
    // ...
}

与提前转换系统一起使用时,最后一种可能是最强大的机制是使用 Spring Boot 部署模型与 GraalVM native 结合引入的封闭世界假设自动生成本机优化代码(源代码和字节码)的功能。图像特征。这里的目标是通过使用本机图像编译器可以开箱即用地分析的代码构造来限制所需的额外本机配置的数量,以提高兼容性,并通过减少反射所需的配置数量来减少占用空间,资源或代理。一个具体的例子是各种形式的提前转换spring.factories (Spring Boot 背后的扩展机制)到优化的程序设计版本,该版本不需要反射,并且可以在应用程序的上下文中过滤掉不必要的条目。

这只是 Spring AOT 的开始,我们打算向[@Configuration功能配置中添加更强大的转换,以通过提前分析来替换运行时反射,该提前分析将自动生成配置类,这些配置类将使用 lambda 和方法引用之类的程序化构造。这将使 GraalVM 本机图像编译器可以立即了解 Spring 配置,而无需任何反射配置或*.class资源。

要记住的一个关键点是,在使用 Spring Native 时,默认情况下在 JVM 上也会使用 AOT 生成的代码,以允许您使用 JVM 允许的短反馈循环来行使“本机友好的代码路径”。您的调试器和所有常规工具。

尽管 Spring AOT 转换当前主要由本机需求驱动,但是其中许多不是本机特定的,并且可能其中一些可以提供优化以在 JVM 上运行 Spring Boot 应用程序。与此类主题一样,重要的是数据驱动,以便我们测量效率和绩效来决定我们的决策。

我们可能会改进 IDE 的集成,现在确保在 IDE 中运行应用程序之前,请先阅读相关文档以进行潜在的手动配置步骤,以更新生成的源代码。

5. 结论

Spring 战略要本地化有两个主要支柱。第一个是使 Spring 基础结构适应本机,而无需对数百万个现有的 Spring Boot 应用程序进行重大更改。其中包括我们在 Spring 顶级项目中所做的更改,以使其对本机友好,@NativeHint我们将在 Spring Native 中成熟的基础架构(例如)和 Spring AOT 构建插件。

第二个支柱比 Spring 本身更广泛,native 是一个具有与 JVM 不同的特性的平台,但是 Java 生态系统需要尽可能地一致,以避免两种非常不同的 Java 风格,这将难以维护。这就是为什么我们与 GraalVM 团队进行深入合作以缩小这一差距的原因。在接下来的几个月中,这项合作将专注于为更广泛的 JVM 生态系统改善本机测试和本机配置。

往期推荐

没有最好的架构,只有更合适的架构。Redis低成本、高可用设计

[合集]JVM内存溢出问题的定位方法

帮你理解【Java垃圾收集机制】

程序员如何画好架构图?

滴滴面试官:为什么不建议把数据库部署在Docker容器内?

基于Redis位图实现用户签到功能

大数据架构PK:Hadoop与MPP的区别

[项目源码]ERP进销存系统

Spring 官宣,要干掉原生 JVM!_第4张图片

你可能感兴趣的:(java,spring,编程语言,jvm,spring,boot)