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

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

我代表團隊和所有貢獻者,很高興宣佈 Spring Native 0.11 版本釋出,它為 Spring Boot 2.6 提供了原生支援。這個雄心勃勃的版本是 Spring 團隊五個月辛勤工作的結果,他們一直在開發一個全新的架構,以將 Spring 對使用 GraalVM 建立原生可執行檔案的支援提升到新的水平。您已經可以在 start.spring.io 上試用它了!

在 Spring Developer Advocate Josh Long 的這部新 Spring Tips 影片中,瞭解更多關於 Spring Native 0.11 的資訊並觀看實際演示。

新的預編譯(AOT)引擎

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

spring boot native

深入來看,AOT 引擎在構建時評估條件,以便生成一個經過最佳化的應用程式上下文和 Spring factories(Spring Boot 背後的外掛系統),這些都專門為您的應用程式量身定製。實際上,這意味著

  • 執行時需要執行的 Spring 基礎設施更少

  • 執行時需要評估的條件更少

  • 更少的反射,因為使用了程式設計式 Bean 註冊

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 在執行時所做的工作。相反,它會啟動一個新的程序,在構建時建立並內省(introspect)應用程式上下文(而不啟動它)。這允許使用 Spring Framework 在執行時執行的一部分功能,並在 Bean 定義層面工作,這要精確得多。

執行時靈活性

在構建時執行這些最佳化意味著執行時靈活性不如常規的 Spring Boot 自動配置模型。您在執行已經編譯好的 Spring Boot 應用程式時,仍然可以更改 HTTP 埠或日誌級別,但例如,您無法在執行時透過使用 Profile 來新增新的 Bean。

這就是為什麼在 JVM 上,AOT 模式是可選的。如果它符合您的需求,這是一個可以使用的最佳化。在原生應用程式中(其設計決定了執行時動態性較低),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));
           }
      });
   }
}

NativeConfiguration 擴充套件點也得到了改進,透過使用 NativeConfigurationRegistry 提供了 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 中輕鬆除錯將在 JVM 上原生執行的程式碼(主應用程式或測試)。

第二個優勢是效率更高。目前,它可以提供大約 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 的原生支援,這與預設使用 Liberica JDK 的 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 生態系統更好的原生支援。Java 8 版本的 GraalVM 不再提供,因為它太老了,無法合理維護,但您仍然可以使用 Java 11 版本的 GraalVM 編譯大多數 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 社群的所有近期活動。

檢視全部