使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

点击关注公众号,利用碎片时间学习


Spring Native是什么

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

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

配置环境

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 Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

配置环境变量

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

检验是否安装成功

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

安装native-image

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

gu install native-image

安装 Docker Desktop for Windows

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

创建Springboot项目

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

完整的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 项目,并且大量减少占用的内存

配置官方文档:

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

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

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

执行maven命令

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

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

构建成功如下图:

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

创建并运行容器

查看所有镜像docker images

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

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 项目,并且大量减少占用的内存

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

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

成功调用接口

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

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

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

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

最后附上Spring Native官方文件:

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

感谢阅读,希望对你有所帮助 :) 

来源:blog.csdn.net/qq_35156196/article/details/127208514

推荐:

最全的java面试题库

使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存
PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下“在看”,加个“星标”,这样每次新文章推送才会第一时间出现在你的订阅列表里。“在看”支持我们吧!

原文始发于微信公众号(Java笔记虾):使用 Spring Native 毫秒级启动 SpringBoot 项目,并且大量减少占用的内存

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/55954.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!