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 本機映象支援 相比,新的 CDS 支援提供了不同的價值主張:透過 CDS 獲得的改進,例如在啟動時間方面,雖然不如本機映象那樣顯著,但仍然非常重要,同時您可以繼續使用常規 JVM,且副作用很少。

Spring Boot 以生產就緒的方式支援 CDS 和 GraalVM 本機映象,並根據您的具體情況和偏好提供選擇。

CDS,JVM 中的隱藏瑰寶

CDS 代表 類資料共享 (Class Data Sharing),這是一項成熟的技術,已在大多數 JVM 中可用和使用,但迄今為止尚未充分發揮其潛力。簡單來說,您可能已經在不知不覺中使用了 CDS,但僅限於最佳化 JDK 類的載入,而您的應用程式或庫中的類可能並未利用它。要解鎖這一點,需要對您的應用程式執行一次訓練執行。

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

  • 必須使用完全相同的 JVM。
  • Classpath 必須指定為 JAR 列表,並避免使用目錄、* 萬用字元和巢狀 JAR。
  • 必須保留 JAR 的時間戳。
  • 在生產執行時使用 CDS 歸檔時,classpath 必須與建立歸檔時使用的 classpath 相同,且順序一致。可以在末尾指定額外的 JAR 或目錄(但這些不會被快取)。

Spring Boot 3.3 透過提供兩項新功能釋放了這一潛力:自解壓可執行 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 profile。
  • CDS_TRAINING_JAVA_TOOL_OPTIONSBP_SPRING_AOT_ENABLED 不能同時使用。

Broadcom 的 Spring 和 Buildpacks 團隊一直在密切合作,利用這些開源特性並將其與額外的 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 搶先體驗版本 配合提供最優效能,後者可以被視為 CDS 的繼任者,具有額外能力,可實現

  • 更快的啟動速度。
  • 更小的容器映象(透過移除 JDK 的 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 社群所有即將舉行的活動。

檢視全部