Spring Boot CDS 支援與 Project Leyden 預期

工程 | Sébastien Deleuze | 2024 年 8 月 29 日 | ...

Spring Boot 開發人員如何以最小的限制,提高其應用程式的執行效率,以便在大多數應用程式上享受這些優勢? 答案是 Spring Boot 3.3 引入的 CDS 支援,它能讓您更快地啟動 Spring Boot 應用程式並消耗更少的記憶體。它基於我幾個月前介紹的 Spring Framework 6.1 引入的基礎

一個關鍵點是,與 GraalVM native image 支援相比,這種新的 CDS 支援提供了不同的價值主張:使用 CDS 獲得的改進不如 native image 在啟動時間上的改進那麼顯著,但它們仍然非常重要,同時您可以繼續使用常規 JVM,副作用非常少。

Spring Boot 以生產就緒的方式支援 CDS 和 GraalVM native image,並根據您的上下文和觀點為您提供選擇。

CDS,JVM 中的隱藏寶石

CDS 代表 Class Data Sharing (類別資料共享),它是一項成熟的技術,已在大多數 JVM 中可用並使用,但到目前為止尚未充分發揮其潛力。 簡而言之,您可能已經在使用 CDS 而不知情,但僅用於優化 JDK 類別的載入,而您的應用程式或函式庫的類別可能沒有利用它。 為了開啟這一點,需要對您的應用程式執行訓練。

您還需要滿足一組約束條件,如果沒有像 Spring Boot 這樣的專用支援,很容易打破這些約束條件。

  • 必須使用完全相同的 JVM。
  • 必須將類別路徑指定為 JAR 列表,並避免使用目錄、* 萬用字元和巢狀 JAR。
  • JAR 的時間戳記必須保留。
  • 當為生產執行使用 CDS 封存檔時,類別路徑必須與用於建立封存檔的路徑相同,且順序相同。 可以在末尾指定其他 JAR 或目錄(但不會被快取)。

Spring Boot 3.3 透過提供 2 個新功能來釋放這種潛力:自解壓縮可執行 JARBuildpacks CDS 支援

自解壓縮可執行 JAR

直接使用可執行 JAR 執行 java -jar my-app.jar 並不是在生產環境中執行應用程式的最有效方式。 這已在 文件中說明,但根據我與 Spring 社群的各種討論,大多數未使用 Buildpacks 的開發人員和營運人員都錯過了這一點。 直到最近,還沒有真正的第一類功能來提供幫助。

Spring Boot 3.3 改變了這一點,並引入了可執行 JAR 自解壓縮的功能,無需任何外部工具,只需使用可能已經可用於執行應用程式的 java 命令即可。

java -Djarmode=tools -jar my-app.jar extract --destination application

CDS file layout

然後,您可以使用以下方式更有效率地執行 Spring Boot 應用程式

java -jar application/my-app.jar

此功能具有超能力:它旨在滿足 CDS(和 Project Leyden)的約束條件。 因此,結合 Spring Framework 對 CDS 訓練執行的支援,您可以為您的 Spring Boot 應用程式建立 CDS 封存檔,如下所示

java -XX:ArchiveClassesAtExit=application.jsa -Dspring.context.exit=onRefresh -jar application/my-app.jar

然後,您可以使用以下方式啟動已啟用 CDS 的應用程式

java -XX:SharedArchiveFile=application.jsa -jar application/my-app.jar

Buildpacks 中的 CDS 和 Spring AOT 啟動支援

自解壓縮可執行 JAR 功能與 CDS 使用結合使用非常靈活,但仍然需要相當多的手動步驟,因此 Spring Boot 和 Buildpacks 提供對 CDS 的整合支援,它

  • 在建立容器映像時自動執行訓練。
  • 將 Spring Boot 可執行 JAR 解壓縮到上面提到的 CDS 友好的檔案佈局中。
  • 將 CDS 封存檔運送到容器中。
  • 在執行容器映像時自動啟用 CDS。

Buildpacks CDS support

https://github.com/sdeleuze/spring-boot-cds-demo 儲存庫所示範,可以使用 Gradle 啟用它,如下所示

tasks.named("bootBuildImage") {
	environment["BP_JVM_CDS_ENABLED"] = "true"
}

或使用 Maven

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<configuration>
		<image>
			<env>
				<BP_JVM_CDS_ENABLED>true</BP_JVM_CDS_ENABLED>
			</env>
		</image>
	</configuration>
</plugin>

在訓練執行期間,Spring bean 會被實例化,而不會啟動 Spring 生存週期,因此在實務中,您可能會觀察到的主要副作用是早期資料庫互動,可以透過配置您的應用程式(或僅使用 CDS_TRAINING_JAVA_TOOL_OPTIONS 環境變數進行訓練執行)來避免這種資料庫互動,如 此處所述。

也可以使用 BP_SPRING_AOT_ENABLED 環境變數觸發 Spring AOT 啟動支援,但請記住以下這些約束條件

  • 在您的 Maven 或 Gradle 建置中啟用 Spring AOT。
  • 可能會配置 Spring AOT 以使用將在部署環境中使用的 Spring 設定檔。
  • CDS_TRAINING_JAVA_TOOL_OPTIONSBP_SPRING_AOT_ENABLED 不能結合使用。

Broadcom 的 Spring 和 Buildpacks 團隊一直密切合作,以利用這些 OSS 功能,並將它們與其他 Tanzu Platform 功能相結合,以便為 Cloud Foundry 或 Kubernetes 提供一流的 CDS 支援,例如允許訓練執行自動配置,使 CDS 能夠像啟用一個標誌一樣容易,沒有副作用,並且還有更多平台級功能即將推出。

資料點

對於在 MacBook M2 上執行的最小 Spring MVC Tomcat 應用程式,我們觀察到,與執行可執行 JAR 相比,結合 CDS 的解壓縮應用程式允許啟動速度快約 1.5 倍,且記憶體消耗低 16%。 如果我們將 Spring AOT 加入其中,我們將獲得啟動速度快約 2 倍,且記憶體消耗低 27%。

WebMVC process startup time (ms) and RSS after startup (Mb)

我們看到了 Petclinic 也有類似的改進。

Petclinic process startup time (ms) and RSS after startup (Mb)

這些值顯然會在效能較差的雲端實例上發生變化,但您可能會觀察到類似的改進比率。

Spring Boot 和 Project Leyden

有趣的是,上面描述的新 extract 命令使用的 CDS 友好的佈局也被設計為在 Project Leyden Early-Access builds 中提供最佳效能,這可以被視為 CDS 的繼承者,具有允許的其他功能

  • 更快的啟動速度。
  • 更小的容器映像(透過刪除 JDK 的 CDS 封存檔,僅保留應用程式的 CDS 封存檔)。
  • 提前預熱,以便在啟動後獲得更好的效能,並更快達到峰值效能。

目前我們觀察到,使用 Project Leyden 的 Spring Boot 應用程式的啟動速度快約 3 倍,而結合 Project Leyden 和 Spring AOT 時,啟動速度快約 4 倍。

Project Leyden data points

我將在即將到來的 Devoxx Belgium 2024 的 Project Leyden 演講中分享更多內容,我很榮幸能與 Java 平台團隊的 Per Minborg 共同主持這次演講。

取得 Spring 電子報

隨時掌握 Spring 電子報的最新資訊

訂閱

搶先一步

VMware 提供訓練和認證,加速您的發展。

了解更多

取得支援

Tanzu Spring 在一個簡單的訂閱中提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援與二進位檔案。

了解更多

近期活動

查看 Spring 社群的所有近期活動。

查看全部