Spring Native 文档
Spring Native 文档
概述
Spring Native支持使用GraalVM native-image编译器将Spring应用编译为本地可执行文件。
与Java虚拟机相比,native images可以为许多类型的工作负载提供更加经济、可持续的托管。包括微服务,适合容器和Kubernetes的工作负载。
使用native image可以提供一些关键的优势,例如即时启动、即时峰值性能和较低的内存消耗。
但是native image也会存在一些缺点,需要权衡利弊。GraalVM native项目预计会随着时间还在慢慢改进。构建本地镜像是一个比较重的操作,比普通应用构建要慢的多。本地镜像预热之后运行时优化手段也比较少。最后,它还不如JVM成熟,在不同环境下会有一些不同的表现。
普通的JVM和native image平台最主要的区别在于:
- 在构建时,需要对你的应用程序从主入口进行静态分析
- 未使用到的部分在构建时会被删除
- 反射、资源、动态代理需要配置
- Classpath在构建时被固定
- 不支持懒加载:可执行文件中的所有内容在启动时都会被加载到内存中
- 一部分代码在构建时就会被执行
- java应用程序某一些方面还有一些限制,不完全支持。
此项目的目标是孵化对 Spring Native(Spring JVM 的替代品)的支持,并提供旨在打包在轻量级容器中的本机部署选项。实际上,此项目最终目标是几乎不加修改的情况下,在这个新平台上支持你的 Spring 应用程序。
模块
Spring Native由以下模块构成:
spring-native
: 运行 Spring Native 所需的运行时依赖,还提供了Native 提示 API。spring-native-configuration
:Spring AOT 插件使用的 Spring 类的配置提示,包括各种 Spring Boot 自动配置。spring-native-docs
: 参考指南,asciidoc 格式。spring-native-tools
:用于校验镜像构建配置和输出的工具。spring-aot
:Maven 和 Gradle 插件共用的 AOT 生成基础设施。spring-aot-test
:测试专用的 AOT 生成基础设施。spring-aot-gradle-plugin
: 调用 AOT 生成的 Gradle 插件。spring-aot-maven-plugin
: 调用 AOT 生成的 Maven 插件。samples
:包含各种示例,包含功能的功能演示使用,并用作集成测试。
开始
构建 Spring Boot 原生应用程序主要有两种方式:
- 使用Spring Boot Buildpacks 支持生成包含本机可执行文件的轻量级容器。
- 使用本机构建工具生成本机可执行文件。
开始使用 Buildpack
本节为您提供使用Cloud Native Buildpacks构建 Spring Boot 本机应用程序的实用概述。这是使用RESTful Web 服务入门指南的实用指南。
系统要求
应该安装 Docker,有关更多详细信息,请参阅获取 Docker。如果您使用的是 Linux,请将其配置为允许非根用户。
1 | 您可以运行docker run hello-world(不使用sudo)来检查 Docker 守护程序是否可以按预期访问。查看Maven或Gradle Spring Boot 插件文档以获取更多详细信息。在 MacOS 上,建议将分配给 Docker 的内存至少增加到8GB,并可能添加更多 CPU。有关详细信息,请参阅此Stackoverflow 答案。在 Microsoft Windows 上,确保启用Docker WSL 2 后端以获得更好的性能。 |
示例项目设置
可以使用以下命令检索完整的“RESTful Web 服务”指南:
1 | git clone https://github.com/spring-guides/gs-rest-service |
验证 Spring Boot 版本
1 | Spring Native 0.12.1 只支持 Spring Boot 2.7.1,如有必要请更改版本。 |
Maven
1 | <parent> |
Gradle Groovy
1 | plugins { |
添加Spring Native 依赖
org.springframework.experimental:spring-native
提供本机配置 API @NativeHint
,以及将 Spring 应用程序作为本机映像运行所需的其他强制类。您只需要使用 Maven 明确指定它。
maven
1 | <dependencies> |
Gradle Groovy
1 | // 不需要用Gradle明确添加spring-native依赖,Spring AOT插件会自动添加。 |
添加 Spring AOT 插件
Spring AOT插件执行改进本机镜像兼容性和占用空间所需的提前转换。( 这些转换也适用于 JVM,因此无论如何都可以应用)
Maven
1 | <build> |
Gradle Groovy
1 | plugins { |
该插件提供了许多选项来自定义转换,有关更多详细信息,请参阅AOT 生成。
启用原生镜像支持
Spring Boot的Cloud Native Buildpacks support让你为你的Spring Boot应用程序构建一个容器。可以使用BP_NATIVE_IMAGE环境变量启用本地镜像构建包,具体如下。
从Spring Native 0.11开始,Liberica Native Image Kit (NIK) is是Buildpacks默认使用的本地镜像编译器。
Maven
1 | <plugin> |
Gradle Groovy
1 | bootBuildImage { |
可以使用BP_NATIVE_IMAGE_BUILD_ARGUMENTS环境变量添加额外的本地j镜像参数。
冻结原生镜像版本
默认情况下,native-image
版本将由 Buildpacks 自动升级到最新版本。您可以使用特定版本的buildpack显式配置 Spring Boot Maven或Gradlejava-native-image
插件,这将冻结 GraalVM 版本,请参阅相关版本映射。例如,如果你想强制使用原生镜像22.1.0
,你可以配置:
Maven
1 | <plugin> |
Gradle Groovy
1 | bootBuildImage { |
使用替代的本地镜像工具
如果你想把Buildpack使用的默认原生镜像工具包(Liberica NIK)改为其他工具包,你可以明确配置Spring Boot的t Maven 或者 Gradle插件,见相关Buildpack文档。例如,如果你想使用GraalVM CE而不是Liberica NIK,你可以配置。
Maven
1 | <plugin> |
Gradle Groovy
1 | bootBuildImage { |
Maven库
配置你的构建,包括spring-native
依赖的所需仓库,如下所示。
Maven
1 | <repositories> |
Gradle Groovy
1 | pluginManagement { |
Spring AOT插件同样也需要在Maven的pom.xml
文件和Gradle的settings.gradle(.kts)
中添加专门的插件库
Maven
1 | <pluginRepositories> |
Gradle Groovy
1 | pluginManagement { |
构建本地应用程序
本地应用程序可以按如下方式构建
1 | --Maven-- |
在本地编译过程中,你会看到大量的WARNING: Could not register reflection metadata信息。它们是预期的,并将在未来的版本中被删除,更多细节见#502
使用GraalVM本地镜像编译器构建本地应用程序将创建一个Linux容器。默认情况下,容器映像被安装在本地。
运行本地应用程序
要运行应用程序,你可以按照常用的方式使用docker,如下所示
1 | docker run --rm -p 8080:8080 rest-service-complete:0.0.1-SNAPSHOT |
如果你喜欢docker-compose
,你可以在项目的根目录写一个docker-compose.yml
,内容如下。
1 | version: '3.1' |
然后运行
1 | docker-compose up |
启动时间应该低于100ms
,相比之下,在JVM上启动大约需要1500ms
现在服务已经启动,访问 localhost:8080/greeting
, 你会看到如下内容
1 | {"id":1,"content":"Hello, World!"} |
开始使用本地构建工具
本节介绍使用GraalVM本地构建工具构建Spring Boot本地应用程序的实用概述。这是一份使用RESTful Web服务入门指南的实用指南。
系统要求
在安装GraalVM本地镜像编译器之前,需要一些先决条件。然后你需要在本地安装原生镜像编译器。本机镜像编译器有不同的发行版本,这里我们主要介绍这两个版本。
基于GraalVM开源库的GraalVM CE和LabsJDK。
基于GraalVM开源库的Bellsoft Liberica Native Image Kit (NIK) 和Liberica JDK。
Linux和MacOS
要在MacOS或Linux上安装本地镜像编译器,我们建议使用SDKMAN。
- 安装SDKMAN.
- 安装GraalVM原生镜像发行版,可以是GraalVM CE(后缀为grl)或Bellsoft Liberica NIK(后缀为nik),这里我们使用Liberica NIK Java 11变体:
SDK install java 22.1.r11-nik
- 确保使用新安装的JDK
sdk use java 22.1.r11-nik
- 运行gu install native-image,将native-image扩展引入JDK
另外,您也可以从 GraalVM 或 Liberica NIK 手动安装构建。如果需要,别忘了适当设置 JAVA_HOME / PATH,并运行 gu install native-image 来引入 native-image 扩展。
Windows
在Windows上,按照 上述说明 安装r GraalVM 或者 Liberica NIK、Visual Studio Build Tools和Windows SDK。由于众所周知的与命令行最大长度有关的Windows限制,确保使用x64 Native Tools Command Prompt而不是常规的Windows命令行来运行Maven或Gradle插件。
项目设置样例
测试用例 “RESTful Web服务 “指南可以使用以下命令下载
1 | git clone https://github.com/spring-guides/gs-rest-service |
校验 Spring Boot 版本
Spring Native 0.12.2只支持Spring Boot 2.7.7,所以必要时要改变版本。
Maven
1 | <parent> |
Gradle Groovy
1 | plugins { |
添加Spring Native 依赖
org.springframework.experimental:spring-native
提供了像@NativeHint
这样的本地配置API,以及将Spring应用作为本地镜像运行所需的其他强制性类。
Maven
1 | <dependencies> |
Gradle Groovy
1 | // 不需要用Gradle明确添加spring-native依赖,Spring AOT插件会自动添加。 |
添加Spring AOT插件
Spring AOT 插件可以提前进行必要的转换,以改善本地镜像的兼容性和体积大小
Maven
1 | <build> |
Gradle Groovy
1 | plugins { |
这个插件提供一系列选项来自定义转换,更多细节见 AOT generation
添加本地构建工具插件
GraalVM 提供了 Gradle 和 Maven 插件可以从你的本地构建种调用本地镜像编译器。下面的例子添加了一个本地配置文件,在打包阶段触发插件。
Maven
1 | <profiles> |
Gradle Groovy
1 | // GraalVM本地构建工具插件被自动应用和配置。 |
当与Spring AOT一起使用时,默认禁用Native Build Tools Gradle工具链支持,以避免目前与以可靠方式识别具有本地功能的JDK有关的限制。参见 这个相关的Gradle问题。
Maven库
配置你的构建,包括spring-native
依赖的发布库,以及Maven Central和Gradle的本地构建工具,如下所示。
Maven
1 | <repositories> |
Gradle Groovy
1 | repositories { |
插件也是如此
Maven
1 | <pluginRepositories> |
Gradle Groovy
1 | pluginManagement { |
构建本地应用程序
本地应用程序可以按如下方式构建
1 | --Maven-- |
该命令在目标目录下创建一个包含Spring Boot应用程序的本地可执行文件。
运行本地应用程序
要运行应用程序,调用以下内容
1 | target/gs-rest-service |
启动时间应该低于100ms
,相比之下,在JVM上启动大约需要1500ms
现在服务已经启动,访问 localhost:8080/greeting
, 你会看到如下内容
1 | {"id":1,"content":"Hello, World!"} |
测试本地应用程序
本地应用程序可按以下方式进行测试。
1 | --Maven-- |
你可以在这里找到关于本地构建工具的更多细节。
支持
Spring Native 现已被 Spring Boot 3 官方原生支持所取代,详情请 参阅相关参考文档。
本节定义了已针对 Spring Native 0.12.2 进行验证的 GraalVM 版本、语言和依赖项,它在本节定义的范围内提供 Beta 支持。如果项目正在使用那些受支持的依赖项,您可以在项目上尝试它,如果出现问题,可以提出错误或 贡献拉取请求。
Beta 支持还意味着将发生重大更改,但将提供并记录迁移路径。
GraalVM
支持 GraalVM 版本 22.1.0,请参阅相关发行说明。影响 Spring 生态系统的 GraalVM 问题在其问题跟踪器上使用标签标识spring
。
语言
支持 Java 11、Java 17 和 Kotlin 1.5+。
Java 编译器
-parameters
标志是必需的,因为.class
在 JVM 上用作回退机制以检索参数名称的资源通常在本机上不可用。Spring Boot 插件会自动在应用它的模块上配置它,但请确保在不是这种情况时明确配置它(通常在多模块项目中或使用 Kotlin 多平台时)。
工具
支持 Maven 和 Gradle(版本 7 或更高版本)。
Spring Boot
Spring Native 0.12.2 已经通过Spring Boot 2.7.7 测试
需要特殊构建配置的启动器
spring-boot-starter-web
- 目前只支持Tomcat .
- 服务端开启HTTPS支持需要添加
--enable-https
org.apache.tomcat.experimental:tomcat-embed-programmatic
依赖被用于优化占用空间
Maven
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-websocket</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.tomcat.experimental</groupId>
<artifactId>tomcat-embed-programmatic</artifactId>
<version>${tomcat.version}</version>
</dependency>Gradle Groovy
1
2
3
4
5implementation('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.apache.tomcat.embed', module: 'tomcat-embed-core'
exclude group: 'org.apache.tomcat.embed', module: 'tomcat-embed-websocket'
}
implementation "org.apache.tomcat.experimental:tomcat-embed-programmatic:${dependencyManagement.importedProperties["tomcat.version"]}"spring-boot-starter-actuator
- 支持WebMvc和WebFlux,以及度量和跟踪基础设施。
- 当为了优化占用空间不使用指标监控时,排除io.micrometer:micrometer-core。
Maven
1
2
3
4
5
6
7
8
9
10<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<exclusions>
<exclusion>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</exclusion>
</exclusions>
</dependency>Gradle Groovy
1
2
3implementation('org.springframework.boot:spring-boot-starter-actuator') {
exclude group: 'io.micrometer', module: 'micrometer-core'
}spring-boot-starter-test