原文:https://foojay.io/today/springboot-3-2-crac/ 前段時間發佈了 Spring 6.1 和 SpringBoot 3.2,它們都完全支持 CRaC(檢查點協調恢復)。 如果你想瞭解有關 CRaC 的更多信息,請隨時閱讀此處: https://docs.a ...
原文:https://foojay.io/today/springboot-3-2-crac/
前段時間發佈了 Spring 6.1 和 SpringBoot 3.2,它們都完全支持 CRaC(檢查點協調恢復)。
如果你想瞭解有關 CRaC 的更多信息,請隨時閱讀此處:
CRaC 是一個 OpenJDK 項目,可以“快照”正在運行的 JVM(Java 虛擬機)並將其狀態(包括你的應用程式)存儲到磁碟。然後,在另一個時間點,你可以將 JVM 從保存的檢查點恢復到記憶體中。這樣,我們就可以啟動應用程式、預熱它並創建檢查點。從保存的檢查點恢復到記憶體主要依賴於磁碟I/O,這意味著它非常快(在毫秒範圍內)。
為了測試 SpringBoot 3.2 對 CRaC 的支持,我將使用 SpringBoot Petclinic 演示。
對於這個小測試,我在我的 M1 Macbook Pro 上使用 4 核和 4GB RAM 在 Parallels 中運行 Ubuntu 22.04。
先決條件
要在 SpringBoot 3.2 中使用 CRaC,你需要具備三件事:
- 支持 CRaC 的 JVM
- org.crac 的依賴項
- 可以存儲檢查點的文件夾
Spring Boot 基礎就不介紹了,推薦看這個實戰項目:
JDK
使用的 JDK(Java 開發工具包)是 Azul Zulu 21.0.1 + CRaC,你可以在此處獲取:
https://www.azul.com/downloads/?os=linux&package=jdk-crac#zulu
JDK 適用於 x64 和 aarch64 CPU 架構以及 JDK 17 和 JDK 21。
推薦閱讀:Java 8 腰斬!Java 17 暴漲 430%!!
許可權
可能需要設置許可權才能使用 CRIU,這意味著在運行演示的 Linux 機器上,你需要執行一次以下命令:
sudo chown root:root $JAVA_HOME/lib/criu
sudo chmod u+s $JAVA_HOME/lib/criu
org.crac。
將 petclinic 存儲庫克隆到本地電腦並添加對 org.crac
庫的依賴項。
由於 CRaC 目前僅在 Linux 上可用,因此你找不到支持 MacOS 和 Windows 的 CRaC 的 JDK。這意味著如果你使用的是 Mac 或 Windows 電腦,則無法針對 CRaC API 進行編碼。為瞭解決這個問題,org.crac 庫提供了與支持 CRaC 的 JDK 中可用的相同 API,但你將在“org.crac”命名空間中找到它,而不是使用“jdk.crac”命名空間。
這樣,即使在 MacOS 和 Windows 上,你也可以針對 CRaC API 進行編碼,而不會出現任何問題,並且一旦你在具有啟用 CRaC 的 JDK 的 Linux 系統上運行它,它將使用 CRaC 功能。
你可以在 Maven Central 上找到 org.crac
,因此你可以添加依賴,如下所示:
Gradle:
implementation 'org.crac:crac:1.4.0'
Maven:
<dependency>
<groupId>org.crac</groupId>
<artifactId>crac</artifactId>
<version>1.4.0</version>
</dependency>
為檢查點創建一個文件夾
在我們測試之前,我們需要確保我們有一個可以存儲檢查點的文件夾,例如 /tmp_checkpoint
在項目文件夾中。
不使用 CRaC 啟動
克隆 petclinic 存儲庫後,你需要構建項目(例如 gradlew clean build),然後就可以運行它。
我們唯一感興趣的是應用程式的啟動時間。我對兩個 JDK 版本(17 和 21)進行了測試,首先,只需從 17 切換到 21,petclinic 應用程式的啟動時間就已經縮短了 500 毫秒!
因此,如果可能的話,你應該儘快切換 JDK,以獲得更好的性能。
通過執行以下命令啟動應用程式:
java -jar spring-petclinic-3.2.0.jar
以下是在不使用 CRaC 的情況下啟動應用程式時的結果:
好的,快了大約 500ms,但啟動仍然需要一些時間,所以讓我們看一下 SpringBoot 3.2 中實現的另一種方法。
自動檢查點
Spring 團隊的工程師有一個好主意,通過在應用程式啟動之前自動創建檢查點來縮短 Spring/SpringBoot 框架的啟動時間。
這是文檔中的描述:
“當設置 -Dspring.context.checkpoint=onRefresh JVM 系統屬性時,在 LifecycleProcessor.onRefresh 階段啟動時會自動創建一個檢查點。此階段完成後,所有非延遲初始化的單例都已實例化,並且 InitializingBean# afterPropertiesSet 回調已被調用;但生命周期尚未開始,並且 ContextRefreshedEvent 尚未發佈。”
為了使用自動檢查點,我們按如下方式啟動應用程式:
java -Dspring.context.checkpoint=onRefresh -XX:CRaCCheckpointTo=./tmp_checkpoint -jar spring-petclinic-3.2.0.jar
執行應用程式後,它將創建檢查點,並將檢查點文件存儲在文件夾 ./tmp_checkpoint
中,然後退出應用程式。
現在你可以通過執行以下命令從檢查點恢復應用程式(這意味著再次啟動它):
java -XX:CRaCRestoreFrom=./tmp_checkpoint
以下是從自動檢查點恢復時與啟動時間相關的結果
這非常酷,我們的啟動時間比原始啟動時間快一個數量級,而無需更改代碼。這也意味著檢查點僅包含框架代碼,而不包含你的應用程式代碼,因為它尚未啟動。
手動檢查點
自動檢查點已經是與啟動時間相關的一個很大的改進,但我們甚至可以通過使用手動檢查點來更快。
使用手動檢查點時,你可以決定何時創建檢查點。
為什麼這很重要?
好吧,你可能想在 10 分鐘後或當你的應用程式完全預熱(大多數/所有代碼已編譯和優化)等時創建一個檢查點。
創建手動檢查點的過程與自動檢查點類似,唯一的區別是你從應用程式外部觸發檢查點,而不是讓框架自動創建檢查點。
在開始之前,請確保檢查點的文件夾為空。
首先,你按如下方式啟動你的應用程式:
java -XX:CRaCCheckpointTo=./tmp_checkpoint -jar spring-petclinic-3.2.0.jar
現在,你需要等待應用程式完全啟動,然後再打開第二個 shell 視窗。
在第二個 shell 視窗中,執行以下命令:
jcmd spring-petclinic-3.2.0.jar JDK.checkpoint
現在你應該看到在第一個 shell 視窗中(你啟動 petclinic 應用程式的位置)創建了一個檢查點並且應用程式已關閉。
你可以通過驗證文件夾 ./tmp_checkpoint
是否包含檢查點文件來檢查應用程式是否已設置檢查點。
現在你可以關閉第二個 shell 視窗。
要從此檢查點恢復應用程式,請執行與自動檢查點相同的命令:
java -XX:CRaCRestoreFrom=./tmp_checkpoint
這個手動觸發的檢查點不僅包含框架代碼,還包含應用程式代碼,這意味著我們應該看到更快的啟動,因為應用程式已經由框架載入並啟動。結果如下:
正如你所看到的,我們已經能夠將 petclinic 應用程式的啟動時間減少另一個數量級,降至 75 毫秒!
信息
由於Spring 6.1和SpringBoot 3.2完全支持CRaC,因此我們不需要對代碼進行修改。這裡的完全支持意味著只要你使用 Spring 資源,框架就會負責在檢查點之前關閉資源併在恢復後恢復它們。
如果你使用其他資源,則需要在相關類中實現 CRaC Resource 介面,併在“beforeCheckpoint()”方法中關閉其他資源(例如打開的文件或套接字連接),併在“beforeCheckpoint()”方法中重新打開其他資源。 afterRestore()' 方法。
判決
正如我們所看到的,使用 CRaC 可以顯著減少 SpringBoot 3.2 應用程式的啟動時間。如果你只是想在不接觸代碼的情況下嘗試一下,只需使用 Spring 6.1 / SpringBoot 3.2 中的自動檢查點功能即可將啟動時間減少一個數量級。
為了儘可能縮短啟動時間,你可以手動創建檢查點,這可以將啟動時間縮短兩個數量級。
CRaC 的優點在於它仍然在普通 JVM 上運行,並且在檢查點/恢復後代碼甚至可以進一步優化。
為了獲得這些結果,我需要向 petclinic 項目添加幾行代碼,如果你想重現這些數字,請隨時在我的 GitHub 存儲庫中克隆 petclinic 項目的副本。
推薦一個開源免費的 Spring Boot 實戰項目:
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
覺得不錯,別忘了隨手點贊+轉發哦!