0
点赞
收藏
分享

微信扫一扫

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)

f12b11374cba 2023-05-17 阅读 33

Spring Native是什么

近几年“原生”一词一直泛滥在云计算、边缘计算等领域中,而原生宠幸的语言也一直都是Golang,Rust等脱离Sandbox运行的开发语言。Java得益于上世纪流行的一次编译,到处执行的理念,流行至今。但也因为这个原因,导致Java程序脱离不了JVM运行环境,使得不那么受原生程序的青睐。在云原生泛滥的今天,臃肿的JVM使Java应用程序对比其他语言显得无比的庞大,各路大神也想了很多方式让Java变的更“原生”。

Spring Native 为使用GraalVM 原生映像编译器将 Spring 应用程序编译为原生可执行文件提供 beta 支持,以提供通常设计为打包在轻量级容器中的原生部署选项。实际上,目标是在这个新平台上支持几乎未修改的 Spring Boot 应用程序。

今天我们就手把手演示一下如何使用Java中的原生框架 Spring Native!

配置环境

OS:Windows10 21H2
IDE:IntelliJ IDEA 2022.1.3
JDK:graalvm-ce-java11-22.2.0
Maven:3.5.4
Docker Desktop for Windows: 4.12.0
Spring Boot:2.7.4
Spring Native:0.12.1

使用 Spring Native 的应用程序应该使用 Java 11 或 Java 17 编译。

构建 Spring Boot 原生应用程序有两种主要方法:

  • 使用Spring Boot Buildpacks 支持生成包含本机可执行文件的轻量级容器。
  • 使用GraalVM 原生镜像 Maven 插件支持生成原生可执行文件。

方法1就是在SpringBoot2.3后,可以使用spring-boot-maven-plugin插件来构建docker镜像,使用mvn spring-boot:build-image命令结合Docker的API来实现Spring Boot 原生应用程序的构建,成功执行后会直接生成一个docker镜像,然后run这个镜像就可以了,不用我们再写Dockerfile了,相关的参数配置都在pom.xml中配置(该插件的configuration标签下,和fabric8或spotify的docker-maven-plugin很相似)。

方法2不需要安装docker,但要安装Visual Studio,然后执行mvn -Pnative package命令后会生成一个可执行文件(.exe),运行即可。

主要区别如下:

1 环境依赖不同

  • 方法1需要安装Docker
  • 方法2需要安装Visual Studio(需要用到部分单个组件:2个MSVC,1个Windows 10 SDK)

2 执行的maven命令不同

  • 方法1是mvn spring-boot:build-image
  • 方法2是mvn -Pnative package

因为每个微服务使用Docker部署而不是exe文件,所以方法1正好符合我的需求,所以后文使用Spring Boot Buildpacks的方式构建Spring Boot原生应用程序。

安装Graal VM

官方下载地址:

https://www.graalvm.org/downloads/

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring


使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_02


配置环境变量

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_maven_03


使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_JAVA_04


使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_05


检验是否安装成功

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_JAVA_06

安装native-image

打开新的cmd,输入以下命令,等待安装

gu install native-image

安装 Docker Desktop for Windows

具体步骤略,按照官方文档操作即可:https://docs.docker.com/desktop/windows/install/

创建Springboot项目

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_maven_07


使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_08


完整的pom如下

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.7.4</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>
 <groupId>com.example</groupId>
 <artifactId>spring-native</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>spring-native</name>
 <description>spring-native</description>
 <properties>
  <java.version>11</java.version>
  <repackage.classifier/>
  <spring-native.version>0.12.1</spring-native.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.experimental</groupId>
   <artifactId>spring-native</artifactId>
   <version>${spring-native.version}</version>
  </dependency>

  <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <optional>true</optional>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
     <excludes>
      <exclude>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
      </exclude>
     </excludes>
     <classifier>${repackage.classifier}</classifier>
     <image>
      <builder>paketobuildpacks/builder:tiny</builder>
      <env>
       <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
       <BPE_DELIM_JAVA_TOOL_OPTIONS xml:space="preserve"> </BPE_DELIM_JAVA_TOOL_OPTIONS>
       <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xms128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
       <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xmx128m</BPE_APPEND_JAVA_TOOL_OPTIONS>
       <BPE_APPEND_JAVA_TOOL_OPTIONS>-Xss256k</BPE_APPEND_JAVA_TOOL_OPTIONS>
       <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:ParallelGCThreads=2</BPE_APPEND_JAVA_TOOL_OPTIONS>
       <BPE_APPEND_JAVA_TOOL_OPTIONS>-XX:+PrintGCDetails</BPE_APPEND_JAVA_TOOL_OPTIONS>
      </env>
     </image>
    </configuration>
   </plugin>
   <plugin>
    <groupId>org.springframework.experimental</groupId>
    <artifactId>spring-aot-maven-plugin</artifactId>
    <version>${spring-native.version}</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>
 <repositories>
  <repository>
   <id>spring-releases</id>
   <name>Spring Releases</name>
   <url>https://repo.spring.io/release</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </repository>
 </repositories>
 <pluginRepositories>
  <pluginRepository>
   <id>spring-releases</id>
   <name>Spring Releases</name>
   <url>https://repo.spring.io/release</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </pluginRepository>
 </pluginRepositories>

</project>

本文介绍的是Spring Native0.12.1版本,其对应的Spring Boot版本必须是2.7.4,以上只是一个最基本的配置案例,实际开发中还需要在spring-boot-maven-plugin插件的configuration标签下配置其他许许多多的参数。

例如docker远程的地址和证书的路径、jvm调优参数、配置文件指定、docker镜像名端口仓库地址等等,最好的方法就是看spring-boot-maven-plugin的官方文档,这里以配置jvm参数为例

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_09


配置官方文档:

https://docs.spring.io/spring-boot/docs/2.6.2/maven-plugin/reference/htmlsingle/#build-image

为了测试我这里配置Springboot项目端口为8888,并且添加了一个获取当前日期的API。

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_maven_10

执行maven命令

mvn clean
mvn '-Dmaven.test.skip=true' spring-boot:build-image

下载完相关依赖后,电脑就会开始构建编译项目,查看任务管理器可以发现在构建和编译过程中CPU利用率很高,内存使用量也很高,根据电脑配置和网络状态不同使用的构建时间也不相同。

构建成功如下图:

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_maven_11


创建并运行容器

查看所有镜像docker images

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_maven_12


spring-native就是构建的镜像

创建并运行容器

docker run -id -p 8888:8888 --name=native-app spring-native:0.0.1-SNAPSHOT 59178df9f49b

Docker Desktop查看日志,发现应用成功启动,启动仅耗时31ms,果然印证了Spring Native启动是毫秒级别这句话。

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_JAVA_13


Docker Desktop查看占用内存,仅46M左右。

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_JAVA_14

图片

成功调用接口

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_15


不使用Spring Native启动应用,使用java -jar来启动项目

使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_spring_16


使用 Spring Native 毫秒级启动 SpringBoot 项目(手把手教学)_JAVA_17


启动耗时1.5秒,占用内存高达238M。

最后附上Spring Native官方文件:

https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/index.html

··········  END  ··············



举报

相关推荐

0 条评论