Spring Native尝鲜

4,376 阅读4分钟

一、概述

Spring Native提供了使用GraalVM 本机图像编译器将Spring应用程序编译为本机可执行文件的支持。与Java虚拟机相比,本机映像可以为许多类型的工作负载提供更便宜,更可持续的托管。这些包括微服务,功能工作负载,非常适合容器和Kubernetes。使用本机映像具有关键优势,例如即时启动,即时峰值性能和减少的内存消耗。

二、安装Graalvm

  1. 安装包下载

1)基础包下载

我们使用的安装包是21.0.0.2 Java8的windows版本

安装包下载:github.com/graalvm/gra…

2)native-image包下载

native-image用于打本地镜像

  1. 安装Graalvm

1)解压安装包

将下载好的安装压缩包解压到文件系统,比如:c:/graavm

2)环境变量配置

配置JAVA_HOME和PATH环境变量。在Windows 7、8和10中,通过命令行设置环境变量的工作方式相同。

将PATH环境变量指向GraalVM的bin目录:

管理员模式下在cmd命令行窗口执行如下命令:

setx /M PATH "C:\graalvm\graalvm-ce-java8-21.0.0.2\bin;%PATH%" 

设置JAVA_HOME环境变量以解析到GraalVM安装目录:

管理员模式下在cmd命令行窗口执行如下命令:

setx /M JAVA_HOME "C:\graalvm\graalvm-ce-java8-21.0.0.2" 

请注意/M,等同于的标志-m需要提升的用户特权。

  1. 安装native-image

1)本地安装native-image

gu -L install native-image-installable-svm-java8-windows-amd64-21.0.0.2.jar

2)查看已安装的组件

gu list

  1. 安装native-image打包依赖环境

1)windows编译依赖环境安装

  1. 访问如下地址:docs.microsoft.com/en-us/visua…

  1. 点击vs_buildtools.exe安装C++编译环境,需要联网下载,大概1.6g大小,离线安装参考Windows C++ build Tools离线安装

  1. 版本测试

    1. 验证Java环境是否正常

输入java -version验证版本

java -version

openjdk version "1.8.0_282" 
OpenJDK Runtime Environment (build 1.8.0_282-b07) 
OpenJDK 64-Bit Server VM GraalVM CE 21.0.0.2 (build 25.282-b07-jvmci-21.0-b06, mixed mode)
  1. 验证native-image打包环境

    1. 创建测试代码:

    public class Example { public static void main(String[] args) { String str = "Native Image is awesome"; String reversed = reverseString(str); System.out.println("The reversed string is: " + reversed); }

        public static String reverseString(String str) {
                if (str.isEmpty())
                        return str;
                return reverseString(str.substring(1)) + str.charAt(0);
        }
    

    }

  2. 编译代码

  3. 打原生镜像包

使用如下命令大巴

native-image Example

打包完成后会成example.exe二进制文件

  1. 运行镜像包

直接在命令行运行example.exe,输出如下:

  1. 总结

1)整个环境搭建最麻烦的地方是windows的C++ 编译工具,文件不仅大,安装且特别慢

2)其他环境(mac、linux)的安装过程后续补充,TODO

3)相关安装包我会上传至百度网盘,方便大家下载,特别graalvm安装需要从github上下载,特别慢,需要科学上网才行,所以我会上传至百度网盘,网盘地址:

链接:https://pan.baidu.com/s/1F6F9sMOJnlOHmlHvqiTQ_A

提取码:7rc1

三、Spring Native示例

官方文档:Spring Native documentation

  1. 创建spring boot项目

创建一个spring boot项目,只包含web项目即可

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

完整的github项目地址:github.com/wenit/labs/…

目前Spring Native 最新版本为 0.9.1仅支持Spring Boot 2.4.4,所以我们创建Spring Boot项目的版本号也必须是这个版本。

pom.xml文件修改spring-boot-starter-parent的版本号为2.4.4

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.4</version>
    <relativePath/>
</parent>
  1. 配置maven仓库

在pom文件中添加如下配置:

将构建配置为包括spring-native依赖项所需的存储库,如下所示:

<repositories>
    <!-- ... -->
    <repository>
        <id>spring-release</id>
        <name>Spring release</name>
        <url>https://repo.spring.io/release</url>
    </repository>
</repositories>

Spring AOT插件还需要专用的插件存储库:

<pluginRepositories>
    <!-- ... -->
    <pluginRepository>
        <id>spring-release</id>
        <name>Spring release</name>
        <url>https://repo.spring.io/release</url>
    </pluginRepository>
</pluginRepositories>
  1. 添加Spring Native依赖项

    org.springframework.experimental spring-native 0.9.1
  2. 添加Spring AOT插件

Spring AOT插件执行提前转换,以改善本机图像兼容性和覆盖范围。

<build>
    <plugins>
        <!-- ... -->
        <plugin>
            <groupId>org.springframework.experimental</groupId>
            <artifactId>spring-aot-maven-plugin</artifactId>
            <version>0.9.1</version>
            <executions>
                <execution>
                    <id>test-generate</id>
                    <goals>
                        <goal>test-generate</goal>
                    </goals>
                </execution>
                <execution>
                    <id>generate</id>
                    <goals>
                        <goal>generate</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
  1. 启用native-image支持

GraalVM提供了一个Maven插件来从您的Maven构建中调用native-image编译器。以下示例添加了一个native-image在package阶段中触发插件的配置文件:

注意修改mainClass为实际main程序类名称

<profiles>
  <profile>
    <id>native-image</id>
    <build>
      <plugins>
        <plugin>
          <groupId>org.graalvm.nativeimage</groupId>
          <artifactId>native-image-maven-plugin</artifactId>
          <version>21.0.0</version>
          <configuration>
            <!-- The native image build needs to know the entry point to your application -->
            <mainClass>com.example.restservice.RestServiceApplication</mainClass>
            <imageName>${project.artifactId}</imageName>
          </configuration>
          <executions>
            <execution>
              <goals>
                <goal>native-image</goal>
              </goals>
              <phase>package</phase>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

在默认的Spring Boot设置中,它们spring-boot-maven-plugin也将在此package阶段运行,并用重新打包的可执行jar替换常规jar。为了避免两个插件之间发生冲突,请确保exec为可执行jar指定一个如下所示的分类器:

<plugins>
    <!-- ... -->
    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <classifier>exec</classifier>
        </configuration>
    </plugin>
</plugins>
  1. 生成本机应用程序

前提条件,需要升级maven版本号至3.3.9,并配置好maven环境变量,我使用的maven最新版本为 3.6.3

然后进入x64 Native Tools Command Prompt命令行环境

点击左下角的开始菜单,点击x64 Native Tools Command Prompt进入命令行环境

在此命令行环境中才能打包

mvn -Pnative-image package -Dmaven.test.skip=true 

占用的大量内存,就一个最简单的Spring Boot项目,打包为native包竟然要5.91G内存😅

  1. 运行本机应用程序

打包完成我们进入项目的target目录,我们可以看到一个二进制文件:

然后我们运行这个文件,双击或者命令行运行都可以,双击二进制文件打开如下窗口:

  1. 测试本机应用程序

服务启动完成后,默认会的web端口是8080,我们在浏览器里访问如下接口,测试下交易:

测试地址:http://localhost:8080/hello

服务器会返回如下报文:

{
    count: 1,
    time: 1616670127994
}

出现如下界面说明服务测试成功

四、常见问题

  1. Error: loading: ... graalvm-ce-java8-21.0.0.2jre\bin\server\jvm.dll

在win10 沙箱环境遇到此问题,切换到graalvm-ce-java11-21.0.0.2无此问题

  1. Default native-compiler executable 'cl.exe' not found via environment variable PATH

解决方法:

添加环境PATH环境变量:

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.28.29910\bin\HostX64\x64

  1. fatal error C1034: stdio.h

解决方法:

1)需要安装

2)进入x64 Native Tools Command Prompt命令行环境

点击左下角的开始菜单,点击x64 Native Tools Command Prompt进入命令行环境

3)进入x64 Native Tools Command Prompt命令行环境后,再执行native-image,进行打包

  1. 打包springboot native image报maven版本过低错误

Failed to execute goal org.graalvm.nativeimage:native-image-maven-plugin:21.0.0:native-image (default) on project spring-native-demo: The plugin org.graalvm.nativeimage:native-image-maven-plugin:21.0.0 requires Maven version 3.3.9

解决方法:

升级maven版本

  1. 未设置main.class导致打包异常

Error: Main entry point class 'com.example.restservice.RestServiceApplication' not found.

解决方法:

在pom.xml的properties中添加main.class配置项目,并指定类名称

<properties> 
        <java.version>1.8</java.version> 
        <main.class>com.example.demo.SpringNativeDemoApplication</main.class> 
</properties>

并在插件中引用此配置项

<plugin> 
        <groupId>org.graalvm.nativeimage</groupId> 
        <artifactId>native-image-maven-plugin</artifactId> 
        <version>21.0.0</version> 
        <configuration> 
                <!-- The native image build needs to know the entry point to your application --> 
                <mainClass>${main.class}</mainClass> 
        </configuration> 
        <executions> 
                <execution> 
                        <goals> 
                                <goal>native-image</goal> 
                        </goals> 
                        <phase>package</phase> 
                </execution> 
        </executions> 
</plugin>
  1. Windows C++ build Tools离线安装

1)离线下载安装包

使用vs_BuildTools.exe 在cmd命令行使用如下命令下载安装包,安装存储在当前目录下的buildTools-C++文件夹下,总大小估计1.6左右

vs_BuildTools.exe --layout buildTools-C++ --add Microsoft.VisualStudio.Workload.VCTools --includeRecommended --lang zh-CN 

这个包比较大下载可能比较慢,我提供的百度网盘地址如下:

链接:https://pan.baidu.com/s/1F6F9sMOJnlOHmlHvqiTQ_A

提取码:7rc1

2)运行vs_setup.exe

下载完毕后,进入buildTools-C++目录,点击vs_setup.exe文件进行安装

3)安装C++ build tools