Spring Boot CDS支援和Leyden專案展望

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

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

一個關鍵點是,這種新的 CDS 支援提供了與 GraalVM 原生映象支援 不同的價值主張: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 透過提供 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

有趣的是,上述新提取命令使用的對 CDS 友好的佈局也旨在為 Project Leyden Early-Access 版本提供最佳效能,這可以看作是 CDS 的繼任者,具有額外的功能,可實現

  • 更快的啟動。
  • 更小的容器映象(透過移除 JDK 的 CDS 存檔,只保留應用程式的存檔)。
  • 提前預熱(Ahead-Of-Time warmup),以便在啟動後獲得更好的效能並更快地達到峰值效能。

我們目前觀察到,使用 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 社群所有即將舉行的活動。

檢視所有