宣佈 Spring Native Beta 版本!

工程 | Sébastien Deleuze | 2021 年 3 月 11 日 | ...

今天,經過一年半的努力,我很高興宣佈推出 Spring Native 的 Beta 版本,並已在 start.spring.io 上提供!

實際上,這意味著除了 Spring 自成立以來支援的常規 Java 虛擬機器之外,我們還增加了 Beta 支援,以便使用 GraalVM 將 Spring 應用程式編譯為原生映象,從而提供一種新的 Spring 應用程式部署方式。支援 Java 和 Kotlin。

這些原生 Spring 應用程式可以作為獨立的可執行檔案部署(無需安裝 JVM),並提供有趣的特性,包括幾乎即時啟動(通常小於 100ms)、即時峰值效能和更低的記憶體消耗,代價是構建時間比 JVM 更長且執行時最佳化更少。

Native Spring Boot web application starting in 38 ms

透過簡單的 mvn spring-boot:build-imagegradle bootBuildImage 命令,您可以生成最佳化的容器映象,其中包含最小的作業系統層和一個小的原生可執行檔案,該檔案僅包含 JDK、Spring 和您的應用程式使用的依賴項所需的位。例如,下面是一個最小的容器映象,其中包含一個 50MB 的可執行檔案,包含 Spring Boot、Spring MVC、Jackson、Tomcat、JDK 和應用程式。

Minimal container image with a 50MB executable containing: Spring Boot

原生應用對於您的 Spring 應用程式來說,有很多適用的使用場景

  • 使用 Spring Cloud Function 的無伺服器應用

  • 更經濟、更可持續地託管您的 Spring 微服務

  • VMware Tanzu 等 Kubernetes 平臺完美契合

  • 希望建立最佳的容器映象來打包您的 Spring 應用程式和服務

我相信出色的 Spring 社群會發現更多用途,例如 Piotr Mińkowski 關於如何使用 Spring Boot 和 GraalVM 在 Knative 上構建原生微服務的這篇精彩教程

團隊協作

Spring Native Beta 版是 Spring 團隊及其專案組合廣泛協作的成果:包括 Spring Framework、Spring Boot,還有 Spring Data、Spring Security、Spring Cloud 和 Spring Initializr。觀看此影片,瞭解 Spring 團隊如何構建 Spring Native Beta 以及它提供了什麼,包括全新 start.spring.io 支援的演示。

我們的原生化工作範圍比 Spring 本身更廣,因為原生化涉及到更廣泛的 JVM 生態系統,因此我們一直在與 GraalVM 團隊合作,以提高原生映象的相容性和精簡度。以下是來自 GraalVM 團隊的 Vojin Jovanovic 的引用:

“與 Spring 團隊合作構建原生 JVM 生態系統是一件非常愉快的事情:他們深厚的技術知識,加上對社群的敏感觸覺,總是能帶來最佳解決方案。最新的 Spring Native 版本及其在 JVM 生態系統中的眾多用途,為原生編譯的廣泛採用鋪平了道路。”

支援範圍

隨著 Spring Native 從 Alpha 階段升級到 Beta 階段,我認為澄清我們提供的支援範圍非常重要。

Alpha 是第一步,我們在許多樣本上進行了大量實驗,並完善了 Spring Native(之前名為 Spring GraalVM Native)的架構、相容性和精簡度,期間有很多破壞性更改。我們還報告了 許多問題,GraalVM 團隊修復了這些問題,以縮小 Spring 應用程式在 JVM 和原生之間的差距。

雖然它仍被視為實驗性版本,但 Beta 意味著 Spring 現在為部分 Spring 生態系統提供了原生支援。如果您的專案使用了受支援的依賴項,您可以嘗試一下,如果出現問題,可以提交 bug貢獻拉取請求。Spring Native 將針對最新的 Spring Boot 2.x 小版本的每個補丁版本釋出新版本。Spring Native 0.9.0 支援 Spring Boot 2.4.3,Spring Native 0.9.1 將支援 Spring Boot 2.4.4 等。可能會出現破壞性更改,但我們會提供遷移路徑的文件。文件質量達到了新的水平:參考文件提供單頁 HTMLPDF 格式,我們還發布了原生提示公共 API 的 Javadoc

start.spring.io

Stéphane Nicollstart.spring.io 上引入了對 Spring Native 的支援以及相關的 IDE 整合,因此從今天起,這可能是探索如何使用 Spring 構建原生應用程式的最簡單方法。

Spring Native support on start.spring.io

新增 Spring Native 依賴項將自動為您的 Maven 或 Gradle 專案配置所需的依賴項和外掛以支援原生應用。應用程式程式碼本身無需更改。

請務必檢查生成的 HELP.md 檔案,該檔案包含有用的連結和文件,同時也會指示您是否選擇了某些已知在原生環境中不受支援的依賴項。

提前轉換 (AOT Transformations)

原生應用與 JVM 不同:類路徑在構建時固定,例如反射或資源需要配置,沒有類的惰性載入(可執行檔案中包含的所有內容都在啟動時載入到記憶體中),並且某些程式碼可以在構建時呼叫。

為了充分利用這些特性並使 Spring 應用程式在原生環境中以最大相容性和最小精簡度執行,Brian Clozel 在此版本中引入了 Spring 提前 (AOT) Maven 和 Gradle 外掛,它們會對您的應用程式執行提前轉換。

第一種轉換旨在基於由出色的 Andy Clement 設計和實現的推理引擎生成 GraalVM 原生配置(反射、資源、代理、native-image 選項),該引擎理解 Spring 程式設計模型和基礎設施。例如,對於每個用 @Controller 註解的類,都會在生成的 reflect-config.json 檔案中新增一個條目。

某些原生配置無法推斷,對於這些情況,我們引入了原生提示註解(詳情請參閱 Javadoc),這使得 Spring Native 能夠以比常規基於 JSON 的原生映象配置更易維護、型別安全且靈活的方式支援原生配置。例如,Spring Native 對 MySQL 驅動程式的支援提供了提示,這些提示將在原生映象的 reflect-config.jsonresource-config.jsonnative-image.properties 中生成正確的條目,如下所示:

@NativeHint(
    trigger = Driver.class,
    options = "--enable-all-security-services",
    types = @TypeHint(types = {
       FailoverConnectionUrl.class,
       FailoverDnsSrvConnectionUrl.class,
       // ...
    }), resources = {
	@ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),
	@ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",
                      isBundle = true)
})
public class MySqlHints implements NativeConfiguration {}

NativeConfiguration 和其他動態配置機制允許更強大和動態的配置生成,但請注意它們的 API 在即將到來的版本中會發生很大變化。

Spring 開發者還可以直接使用特定於應用程式的原生提示註解他們的 @Configuration@SpringBootApplication 類,例如透過 RestTemplateWebClient 等程式設計式 API 將 Book 類序列化為 JSON

@TypeHint(types = Book.class)
@SpringBootApplication
public class WebClientApplication {
    // ...
}

在使用提前轉換系統時,最後一個也是可能最強大的機制是,結合 Spring Boot 部署模型引入的封閉世界假設和 GraalVM 原生映象特性,自動生成原生最佳化程式碼(原始碼和位元組碼)的能力。這裡的目標是透過使用原生映象編譯器可直接分析的程式碼結構,減少所需的額外原生配置量以提高相容性,並透過減少反射、資源或代理所需的配置量來降低精簡度。一個具體的例子是將各種 spring.factories(Spring Boot 背後的擴充套件機制)提前轉換為最佳化的程式設計式版本,該版本不需要反射,並過濾掉應用程式上下文中不必要的條目。

這只是 Spring AOT 的開始,我們打算新增更強大的轉換,例如將@Configuration 轉換為函式式配置,用提前分析代替執行時反射,該分析將自動生成使用 Lambda 表示式和方法引用等程式設計式結構的配置類。這將使 GraalVM 原生映象編譯器能夠直接理解 Spring 配置,而無需任何反射配置或 *.class 資源。

需要記住的關鍵一點是,使用 Spring Native 時,這些 AOT 生成的程式碼在 JVM 上預設也會被使用,以便您可以在 JVM 提供的短反饋週期內,使用偵錯程式和所有常規工具來測試“原生友好程式碼路徑”。

雖然 Spring AOT 轉換目前主要由原生需求驅動,但其中許多轉換並非特定於原生,並且一些轉換可能為在 JVM 上執行 Spring Boot 應用程式提供最佳化。像往常一樣,對於這類主題,資料驅動非常重要,因此我們將衡量效率和效能來指導我們的決策。

我們可能會完善 IDE 整合,目前請務必閱讀相關文件,瞭解在 IDE 中執行應用程式之前更新生成原始碼的潛在手動配置步驟。

結論

Spring 實現原生化的策略主要有兩大支柱。第一個是將 Spring 基礎設施適配到原生環境,同時不對數百萬現有的 Spring Boot 應用程式進行重大更改。這包括我們在 Spring 頂級專案中進行的改動,使其對原生環境友好,以及我們在 Spring Native 中正在完善的基礎設施,例如 @NativeHint 和 Spring AOT 構建外掛。請查閱我們的路線圖,瞭解有關後續步驟的更多資訊。

第二個支柱比 Spring 本身更廣泛,原生是一種與 JVM 特性不同的平臺,但 Java 生態系統需要儘可能保持一致,以避免出現兩種差異很大的 Java 變體,這將給維護帶來挑戰。這就是我們與 GraalVM 團隊密切合作以彌合這一差距的原因。這種合作在未來幾個月將重點關注改進更廣泛 JVM 生態系統的原生測試和原生配置。

Spring 開發者可以透過我們提供的各種示例瞭解更多關於原生化的資訊,前往 start.spring.io 測試我們新的原生支援,閱讀更新的參考指南,閱讀發行說明,特別是如果您是從舊版本升級,或者甚至貢獻您喜歡的依賴項的支援。如果您想了解更多關於相關的 Spring 商業支援,您也可以聯絡我們

最後,我要向已經提供了許多有用反饋和貢獻的 Spring 社群、給予了令人驚歎的協作的 GraalVM 團隊以及為使 Spring 開發者更容易採用原生化而努力工作的更廣泛的 Spring 團隊致以最誠摯的謝意。

盡情體驗吧!

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

快人一步

VMware 提供培訓和認證,助您快速進步。

瞭解更多

獲取支援

Tanzu Spring 透過一項簡單的訂閱,為 OpenJDK™、Spring 和 Apache Tomcat® 提供支援和二進位制檔案。

瞭解更多

即將到來的活動

檢視 Spring 社群所有即將到來的活動。

檢視全部