使用 Spring Native 毫秒級啟動 SpringBoot 項目,并且大量減少占用的內(nèi)存
回復架構師獲取資源
大家好,我是你們的朋友架構君,一個會寫代碼吟詩的架構師。
'javajgs.com';
原文:
blog.csdn.net/qq_35156196/article/details/127208514
Spring Native是什么
近幾年“原生”一詞一直泛濫在云計算、邊緣計算等領域中,而原生寵幸的語言也一直都是Golang,Rust等脫離Sandbox運行的開發(fā)語言。Java得益于上世紀流行的一次編譯,到處執(zhí)行的理念,流行至今,但也因為這個原因,導致Java程序脫離不了JVM運行環(huán)境,使得不那么受原生程序的青睞。在云原生泛濫的今天,臃腫的JVM使Java應用程序對比其他語言顯得無比的龐大,各路大神也想了很多方式讓Java變的更“原生”。
Spring Native 為使用GraalVM 原生映像編譯器將 Spring 應用程序編譯為原生可執(zhí)行文件提供 beta 支持,以提供通常設計為打包在輕量級容器中的原生部署選項。實際上,目標是在這個新平臺上支持幾乎未修改的 Spring Boot 應用程序。
配置環(huán)境
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 支持生成包含本機可執(zhí)行文件的輕量級容器。 使用GraalVM 原生鏡像 Maven 插件支持生成原生可執(zhí)行文件。
方法1就是在SpringBoot2.3后,可以使用spring-boot-maven-plugin插件來構建docker鏡像,使用mvn spring-boot:build-image命令結合Docker的API來實現(xiàn)Spring Boot 原生應用程序的構建,成功執(zhí)行后會直接生成一個docker鏡像,然后run這個鏡像就可以了,不用我們再寫Dockerfile了,相關的參數(shù)配置都在pom.xml中配置(該插件的configuration標簽下,和fabric8或spotify的docker-maven-plugin很相似)。
方法2不需要安裝docker,但要安裝Visual Studio,然后執(zhí)行mvn -Pnative package命令后會生成一個可執(zhí)行文件(.exe),運行即可。
主要區(qū)別如下
1 環(huán)境依賴不同
方法1需要安裝Docker 方法2需要安裝Visual Studio(需要用到部分單個組件:2個MSVC,1個Windows 10 SDK)
2 執(zhí)行的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/


配置環(huán)境變量



檢驗是否安裝成功

安裝native-image
打開新的cmd,輸入以下命令,等待安裝
gu install native-image
安裝 Docker Desktop for Windows
具體步驟略,按照官方文檔操作即可:
https://docs.docker.com/desktop/windows/install/
創(chuàng)建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,以上只是一個最基本的配置案例,實際開發(fā)中還需要在spring-boot-maven-plugin插件的configuration標簽下配置其他許許多多的參數(shù)。
例如docker遠程的地址和證書的路徑、jvm調優(yōu)參數(shù)、配置文件指定、docker鏡像名端口倉庫地址等等,最好的方法就是看spring-boot-maven-plugin的官方文檔,這里以配置jvm參數(shù)為例

配置官方文檔:
https://docs.spring.io/spring-boot/docs/2.6.2/maven-plugin/reference/htmlsingle/#build-image
為了測試我這里配置Springboot項目端口為8888,并且添加了一個獲取當前日期的API。


執(zhí)行maven命令
mvn clean
mvn '-Dmaven.test.skip=true' spring-boot:build-image
下載完相關依賴后,電腦就會開始構建編譯項目,查看任務管理器可以發(fā)現(xiàn)在構建和編譯過程中CPU利用率很高,內(nèi)存使用量也很高,根據(jù)電腦配置和網(wǎng)絡狀態(tài)不同使用的構建時間也不相同。
構建成功如下圖:

創(chuàng)建并運行容器
查看所有鏡像docker images

spring-native就是構建的鏡像
創(chuàng)建并運行容器
docker run -id -p 8888:8888 --name=native-app spring-native:0.0.1-SNAPSHOT 59178df9f49b
在Docker Desktop查看日志,發(fā)現(xiàn)應用成功啟動,啟動僅耗時31ms,果然印證了Spring Native啟動是毫秒級別這句話。

在Docker Desktop查看占用內(nèi)存,僅46M左右。

成功調用接口

不使用Spring Native啟動應用,使用java -jar來啟動項目


啟動耗時1.5秒,占用內(nèi)存高達238M。
最后附上Spring Native官方文件:
https://docs.spring.io/spring-native/docs/current/reference/htmlsingle/index.html
這些年小編給你分享過的干貨
2.優(yōu)質ERP系統(tǒng)帶進銷存財務生產(chǎn)功能(附源碼)
3.優(yōu)質SpringBoot帶工作流管理項目(附源碼)
5.SBoot+Vue外賣系統(tǒng)前后端都有(附源碼)

轉發(fā)在看就是最大的支持??
