GraalVM和Spring Native嚐鮮,一步步讓Springboot啟動飛起來,66ms完成啟動

南瓜慢說發表於2023-01-29

簡介

GraalVM是高效能的JDK,支援Java/Python/JavaScript等語言。它可以讓Java變成二進位制檔案來執行,讓程式在任何地方執行更快。這或許是Java與Go的一場戰爭?

下載安裝GraalVM

安裝GraalVM

首先到官網下載,我是直接到GitHub Release Page下載的,請下載對應的系統包,我下載如下:

graalvm-ce-java11-darwin-amd64-22.3.0.tar.gz

下載後解壓到某個目錄,我的如下:

/Users/larry/Software/graalvm-ce-java11-22.3.0

接著測試對應的程式是否可以正常執行,如java --version。在Mac上會報錯如下:

is damaged and can’t be opened.

所以需要執行下面語句:

$ sudo xattr -r -d com.apple.quarantine /Users/larry/Software/graalvm-ce-java11-22.3.0

注意修改對應的目錄。

然後就可以執行了:

$ ./java --version
openjdk 11.0.17 2022-10-18
OpenJDK Runtime Environment GraalVM CE 22.3.0 (build 11.0.17+8-jvmci-22.3-b08)
OpenJDK 64-Bit Server VM GraalVM CE 22.3.0 (build 11.0.17+8-jvmci-22.3-b08, mixed mode, sharing)

安裝native-image

這個工具用來把Java程式轉化為本地二進位制包,安裝如下:

$ ./gu install native-image
Downloading: Component catalog from www.graalvm.org
Processing Component: Native Image
Downloading: Component native-image: Native Image from github.com
Installing new component: Native Image (org.graalvm.native-image, version 22.3.0)

配置環境

配置環境變數

因為這個GraalVM還不夠成熟,我不想一直使用,就透過一個命令來切換,配置如下:

export GraalVM_HOME=/Users/larry/Software/graalvm-ce-java11-22.3.0/Contents/Home
alias switchOnGraalVM='export PATH=$GraalVM_HOME:$PATH'
alias switchOnGraalVMJavaHome='export JAVA_HOME=/Users/larry/Software/graalvm-ce-java11-22.3.0/Contents/Home'

alias switchOffGraalVM='export PATH=`echo $PATH | tr ":" "\n" | grep -v "graalvm" | tr "\n" ":"`'
alias switchOffGraalVMJavaHome='export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_212.jdk/Contents/Home'

配置IDEA

可以在IDEA上配置對應的JDK,這樣開發的時候可以使用:

整合Spring Native與Spring Boot

普通Spring Boot程式

新來建立一個普通的Spring Boot Web程式,主要Java程式碼如下:

@SpringBootApplication
@RestController
@RequestMapping("/")
public class SpringbootNativeGraalVMMain {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootNativeGraalVMMain.class, args);
    }

    @GetMapping("/hi-graalvm")
    public String hi() {
        return "This message is from Spring Boot built/run by GraalVM/Spring Native";
    }
}

啟動時長為1.193秒,還不錯。我電腦還不錯。

整合Spring Native

新增依賴:

<dependency>
  <groupId>org.springframework.experimental</groupId>
  <artifactId>spring-native</artifactId>
  <version>${spring-native.version}</version>
</dependency>

新增外掛,這個外掛非常重要,不然會有各種錯誤:

<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.experimental</groupId>
      <artifactId>spring-aot-maven-plugin</artifactId>
      <version>0.11.5</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>

新增以下外掛來打包生成可執行程式:

<profiles>
  <profile>
    <id>native</id>
    <properties>
      <repackage.classifier>exec</repackage.classifier>
      <native-buildtools.version>0.9.11</native-buildtools.version>
    </properties>
    <dependencies>
      <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-launcher</artifactId>
        <scope>test</scope>
      </dependency>
    </dependencies>
    <build>
      <plugins>
        <plugin>
          <groupId>org.graalvm.buildtools</groupId>
          <artifactId>native-maven-plugin</artifactId>
          <version>${native-buildtools.version}</version>
          <extensions>true</extensions>
          <executions>
            <execution>
              <id>test-native</id>
              <phase>test</phase>
              <goals>
                <goal>test</goal>
              </goals>
            </execution>
            <execution>
              <id>build-native</id>
              <phase>package</phase>
              <goals>
                <goal>build</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
      </plugins>
    </build>
  </profile>
</profiles>

然後透過以下命令來build包,時間會長很多,因為要轉化為二進位制可執行檔案:

$ mvn clean package -Pnative

兩分多鐘後完成,生成了一個可執行檔案,執行如下:

$ target/spring-boot-native-graalvm

結果只花了0.066秒,即66毫秒就可以了,這也太快了吧。

訪問介面也是正常的:

用Docker啟動

先啟動本地的Docker,然後新增依賴如下:

<plugin>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-maven-plugin</artifactId>
  <configuration>
    <classifier>${repackage.classifier}</classifier>
    <image>
      <builder>paketobuildpacks/builder:tiny</builder>
      <env>
        <BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
      </env>
    </image>
  </configuration>
</plugin>

透過以下命令打出Docker映象:

mvn spring-boot:build-image

可能會花費很長時間,需要下載一些工具與映象。

打包成功後,多了映象:

$ docker images | grep graalvm
spring-boot-native-graalvm                               1.0-SNAPSHOT                                     d2c8d5c52a3c        42 years ago        85.8MB 

啟動如下:

$ docker run --rm spring-boot-native-graalvm:1.0-SNAPSHOT -p 8080:8080

啟動時間為59ms,更短了。

注意

  • 直接透過native-image命令來將jar包轉化為可執行檔案,如遇到各種問題,勸大家放棄嘗試,這也是Spring Native存在的價值。別問我為什麼知道,哈哈~~
  • 要注意切換對應的Java程式和Java Home,不然build包會報錯。
  • 看Spring Native的包名是experimental的,離生產應該還有距離,不要輕易在生產上用。

程式碼

程式碼請看GitHub: https://github.com/LarryDpk/p...


References:

Quick Start Guide

GraalVM Quick Reference

GraalVM Native Image Quick Reference v1

向雲原生靠近 | 體驗 GraalVM 靜態編譯位元組碼,嘗試 “超聲波 Java” - Quarkus

相關文章