Spring Native项目支持使用GraalVM将Spring应用程序打包为原生镜像。
与JVM可执行文件相比,原生镜像具有更快的启动时间( <100ms )和更低的内存消耗。但是,构建原生镜像比基于JVM的映像需要更多的时间。
该项目仍处于测试阶段,但已经支持大多数Spring组合模块,包括Spring Framework,Spring Boot, Spring Security, 和 Spring Cloud。
它的特性使它非常适合使用Spring Cloud功能构建无服务器 serverless 应用程序,并将其部署到Azure Functions、AWS Lambda或Knative等平台。
本文将指导您构建一个Spring Boot应用程序,该应用程序使用Spring native编译为本机可执行文件。您可以在GitHub上找到源代码: https://github.com/ThomasVitale/spring-tutorials/tree/master/spring-native-graalvm
使用Spring Native引导应用程序
当从spring initializer引导项目时( https://start.spring.io/ ),可以将Spring Native添加到应用程序中。
生成的项目将包含对SpringNative项目和Spring AOT插件的依赖,Spring AOT插件用于将应用程序源代码编译为本机可执行文件,同时提高兼容性和占用空间。
build.gradle
文件如下所示。
plugins { id 'org.springframework.boot' version '2.4.3' id 'io.spring.dependency-management' version '1.0.11.RELEASE' id 'java' id 'org.springframework.experimental.aot' version '0.9.0' } group = 'com.thomasvitale' version = '0.0.1-SNAPSHOT' sourceCompatibility = '11' repositories { maven { url 'https://repo.spring.io/release' } mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-webflux' testImplementation 'org.springframework.boot:spring-boot-starter-test' testImplementation 'io.projectreactor:reactor-test' } test { useJUnitPlatform() } bootBuildImage { builder = 'paketobuildpacks/builder:tiny' environment = ['BP_NATIVE_IMAGE': 'true'] }
您可以使用熟悉的Spring Boot插件(Gradle或Maven)及其嵌入式云本地Buildpacks支持,从应用程序构建本机映像。JVM和GraalVM映像之间的选择由bootBuildImage任务中的 BP_NATIVE_IMAGE
属性定义,该属性在使用Spring Initialzr时预先配置。
用Spring WebFlux定义REST端点
让我们用Spring WebFlux定义一个REST端点,以便测试应用程序。
在Initializer生成的 SpringNativeGraalvmApplication
类中,可以使用路由器函数或 @RestController
注释类添加REST端点。我们还是用前一种方法吧。
package com.thomasvitale.demo; import reactor.core.publisher.Mono; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; import org.springframework.web.reactive.function.server.RouterFunction; import org.springframework.web.reactive.function.server.ServerResponse; import static org.springframework.web.reactive.function.server.RouterFunctions.route; import static org.springframework.web.reactive.function.server.ServerResponse.ok; @SpringBootApplication public class SpringNativeGraalvmApplication { public static void main(String[] args) { SpringApplication.run(SpringNativeGraalvmApplication.class, args); } @Bean RouterFunction<ServerResponse> routes() { return route() .GET("/", request -> ok().body(Mono.just("Spring Native and Beyond!"), String.class)) .build(); } }
然后,在Initializer生成的 SpringNativeGraalVmaApplicationTests
类中,可以为REST端点添加集成测试。
package com.thomasvitale.demo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.reactive.server.WebTestClient; @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @AutoConfigureWebTestClient class SpringNativeGraalvmApplicationTests { @Autowired private WebTestClient webClient; @Test void whenGetBooksThenReturn() { webClient .get().uri("/") .exchange() .expectStatus().is2xxSuccessful() .expectBody(String.class).isEqualTo("Spring Native and Beyond!"); } }
将应用程序作为可执行JAR运行
项目中的Spring本机依赖项将优化应用程序启动时间和内存消耗,这要感谢Spring AOT插件,即使它作为可执行JAR运行。让我们试试看。
首先,打开一个终端窗口,导航到项目的根文件夹,然后运行以下命令。
$ ./gradlew bootRun
如果没有Spring AOT,应用程序的启动速度将比相应的版本更快。让我们尝试调用REST端点。
$ curl http://localhost:8080 Spring Native and Beyond!
将应用程序作为本机映像运行
现在,让我们尝试使用Spring native和GraalVM构建并运行一个本机映像。
使用Spring Boot插件构建本机映像非常简单。确保Docker引擎正在运行,然后执行以下命令。请注意,这将需要几分钟,很大程度上取决于你的笔记本电脑的CPU和内存特性。
$ ./gradlew bootBuildImage
结果将是一个 spring-native-graalvm:0.0.1-SNAPSHOT
的镜像你可以和Docker一起跑。
$ docker run --name spring-native-graalvm -p 8080:8080 spring-native-graalvm:0.0.1-SNAPSHOT
使用Spring Native的应用程序通常在不到100ms的时间内启动,这取决于您机器的可用资源。
再次调用REST端点,以确保应用程序作为本机映像运行时仍能正常工作。
$ curl http://localhost:8080 Spring Native and Beyond!
结论
在本文中,我介绍了如何快速引导Spring Boot应用程序,并使用Spring native和GraalVM将其编译为本机可执行文件。