全新的 AOT 引擎將 Spring Native 推向新高度

工程 | Sébastien Deleuze | 2021 年 12 月 09 日 | ...

我謹代表團隊以及所有做出貢獻的人,非常高興地宣佈 Spring Native 0.11 的釋出,它為 Spring Boot 2.6 提供了原生支援。這次雄心勃勃的釋出是 Spring 團隊五個月辛勤工作的成果,他們開發了一個全新的架構,將 Spring 對使用 GraalVM 建立原生可執行檔案的支援提升到新的水平。您可以在 start.spring.io 上進行體驗!

想了解更多關於 Spring Native 0.11 的資訊,並在 Spring Developer Advocate Josh Long 的這個新的 Spring Tips 影片中觀看它的實際應用。

全新的提前編譯 (AOT) 引擎

最大的變化無疑是引入了一個新的 AOT 引擎,它在構建時對您的 Spring 應用程式進行深度分析,以轉換和最佳化您的應用程式,並生成所需的 GraalVM 原生配置。這些轉換由 Maven 和 Gradle 的 Spring AOT 外掛執行。

spring boot native

深入來看,AOT 引擎在構建時評估條件,以便生成針對您的應用程式定製的最佳化應用程式上下文和 Spring factories(Spring Boot 背後的外掛系統)。實際上,這意味著:

AOT 引擎根據被識別為活動的 Bean、對 Spring 程式設計模型的瞭解以及 Spring Native 捆綁或您的應用程式本身提供的原生提示,推斷出執行您的應用程式作為原生可執行檔案所需的原生配置。

aot architecture

我們要特別感謝 Stéphane Nicoll,他領導了這款新的 AOT 引擎的設計和實現。

記憶體佔用減少

AOT 引擎的一個關鍵優勢是它支援原生可執行檔案更小的記憶體佔用,因為原生配置更準確,所需的反射更少,執行時所需的 Spring 基礎設施也更少。

與 Spring Native 0.10 相比,Spring Native 0.11 的記憶體佔用平均減少了 **20%** 到 **26%**!下圖展示了幾個示例應用程式的資料點。

native rss

啟動速度更快

與 0.10 版本相比,Spring Native 0.11 的啟動時間快了 **16%** 到 **35%**,因為一部分處理已從執行時轉移到構建時。由於在此次次要版本更新中未能對 Spring Boot 和 Spring Framework 的內部架構進行精細調整,因此仍有改進的空間。

native startup

相容性改進

AOT 引擎也更加準確,因為它不嘗試分析 Spring 註解或各種型別來複制 Spring 在執行時所做的事情。相反,它會分叉一個新程序,在構建時(不啟動)建立和內省應用程式上下文。這允許使用 Spring Framework 在執行時所做的部分功能,並且在 Bean 定義級別上工作,這要準確得多。

執行時靈活性

在構建時進行這些最佳化意味著與常規的 Spring Boot 自動配置模型相比,執行時靈活性會降低。在執行已編譯的 Spring Boot 應用程式時,您仍然可以更改 HTTP 埠或日誌級別,但例如您無法使用配置檔案在執行時新增新的 Bean。

因此,在 JVM 上,AOT 模式是可選的。這是一種可以根據您的需求選擇使用的最佳化。而在原生模式下(其設計本身執行時動態性就差很多),這是強制性的。另外,請記住,目前條件是在構建時評估的。將來我們可能會使其更加靈活,以適應大多數用例。

擴充套件點

新引擎提供了一個可插拔的模組化架構,使用者(如您或 Spring 專案團隊)可以利用它來支援各種新功能。

例如,檢視 `BeanFactoryNativeConfigurationProcessor` 擴充套件點的實現,它會自動為使用 `@RequestScope` 或 `@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS)` 註解的 Bean 提前建立類代理。

public class ScopeNativeConfigurationProcessor implements BeanFactoryNativeConfigurationProcessor {

   @Override
   public void process(ConfigurableListableBeanFactory beanFactory, NativeConfigurationRegistry registry) {
       new BeanFactoryProcessor(beanFactory).processBeansWithAnnotation(Scope.class, (beanName, beanType) -> {
           Scope scope = beanFactory.findAnnotationOnBean(beanName, Scope.class);
           if (scope.proxyMode() == ScopedProxyMode.TARGET_CLASS) {
               registry.proxy().add(NativeProxyEntry.ofClass(beanType, ProxyBits.NONE,
                       ScopedObject.class, Serializable.class, AopInfrastructureBean.class));
           }
      });
   }
}

透過使用 `NativeConfigurationRegistry`,`NativeConfiguration` 擴充套件點已得到改進,以提供 API。

public interface NativeConfiguration {
   default boolean isValid(AotOptions aotOptions) { return true; }
   default void computeHints(NativeConfigurationRegistry registry, AotOptions aotOptions) { return; }
}

這些擴充套件點在 `META-INF/spring.factories` 中定義然後被發現,所以 您可以提供自己的

AOT 測試支援

我們在 Spring Native 0.11 上所做的大部分工作都集中在 AOT 程式碼路徑的測試支援實現上,以將原生測試支援提升到全新的水平。其結果是相容性得到了顯著提高,支援更多種類的測試。

結合 Native Build Tools 提供的出色的 JUnit 5 原生支援,您可以像在 JVM 上一樣執行您的 Spring Boot、Spring Framework 或純 JUnit 測試。

與 Spring 無關,Mockito 尚不支援,但正在進行相關工作,以便將來能夠支援。

JVM 上的 AOT

在將在 JVM 上執行的應用程式上執行 AOT 轉換有兩個主要好處。

第一個好處是在 IDE 中輕鬆除錯將在原生模式下執行的程式碼(主應用程式或測試)。

第二個優勢是更高的效率。目前,它提供了大約 **4%** 到 **17%** 的更小記憶體佔用。

jvm rss

AOT 模式還將應用程式啟動速度提高了 **3%** 到 **24%**。

jvm startup

請注意,直到現在,我們還沒有特別關注 JVM 的效率,因此在未來的版本中很可能有改進的機會。

Bellsoft Liberica NIK

Bellsoft Liberica Native Image Kit (NIK) 是一個基於 GraalVM 開源倉庫 和 Liberica JDK 的原生映像編譯器發行版。截至 Spring Native 0.11,它預設用於 Buildpacks 的原生支援,這與 JDK 端預設使用 Liberica JDK 保持一致。您也可以透過其 SDKMAN 整合或 下載 並安裝它來本地安裝。

今年早些時候,團隊與 BellSoft 一起 宣佈,使用 Liberica Native Image Kit 的 VMware 客戶可以執行他們的 Spring 應用程式作為原生可執行檔案,並確信它們得到了完全支援。

新基線

Spring Native 0.11 也為我們提供了基於 Spring Boot 2.6 提供新基線的機會。

GraalVM 21.3 同時支援 Java 11 和 Java 17,並利用 條件原生配置 和其他相關改進,以實現更小的記憶體佔用和對 JVM 生態系統的更好原生支援。不再提供 GraalVM 的 Java 8 版本,因為它已過時,難以維護,但您仍然可以使用 GraalVM 的 Java 11 版本來編譯大多數 Java 8 應用程式。支援 Native Build Tools 0.9.8,我們將繼續合作進行改進和完善。

Spring Boot 3 的一流原生支援

我認為 Spring Native 0.11 實現了其為 Spring Boot 提供成熟的原生選項的目標。Spring 團隊現在可以專注於下一步:在 Spring Framework 6、Spring Boot 3 及相關專案組合中提供精細的原生支援。

請記住,我們所做的所有 Spring Native 工作都是與其他 Spring 專案密切合作完成的,但沒有進行深入的架構更改。隨著 AOT 和原生技術成為 Spring Boot 3 和 Spring Framework 6 的主要主題,這些功能的質量、可維護性和易用性將達到新的水平。AOT 引擎將得到改進並直接整合到 Spring Framework 中。其他專案,如 Spring Data 或 Spring Security,將能夠為其範圍提供原生支援(並對其進行測試),而 Spring Boot 將在其外掛和文件中提供開箱即用的 AOT 和原生可執行檔案支援。

boot3 aot architecture

我們將加強與 GraalVM 團隊和 JVM 生態系統的合作,以便為 Spring 之外的各種庫提供原生配置,無論是直接在這些庫中,還是在直接整合到 Native Build Tools 級別的原生配置倉庫中。

我們計劃在 2022 年 5 月的 Spring Boot 3 milestone 3 中開始提供開箱即用的 GraalVM 原生支援,利用我們在 Spring Native 工作中所學到的一切。通用釋出計劃於 2022 年底。我們有很多令人興奮的計劃,但現在,讓我們花點時間與 Spring 團隊和貢獻的 Spring 社群成員一起慶祝這次釋出。乾杯!

獲取 Spring 新聞通訊

透過 Spring 新聞通訊保持聯絡

訂閱

領先一步

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

瞭解更多

獲得支援

Tanzu Spring 提供 OpenJDK™、Spring 和 Apache Tomcat® 的支援和二進位制檔案,只需一份簡單的訂閱。

瞭解更多

即將舉行的活動

檢視 Spring 社群所有即將舉行的活動。

檢視所有