写点什么

Spring Native 0.11 发布,带来新的 AOT 引擎和性能优化

作者:Robert Lu
  • 2021 年 12 月 13 日
  • 本文字数:3250 字

    阅读完需:约 11 分钟

Spring Native 0.11已于 2021 年 12 月 9 日发布。


这个宏大的版本是 Spring 团队五个月辛勤工作的结果,他们一直在研究一个全新的架构,将让 Spring 使用 GraalVM 创建原生可执行文件的方式提升到一个新的水平。你目前已经可以已经在start.spring.io上试用了!


想了解有关 Spring Native 0.11 的更多信息,可以查看来自 Spring 布道师的新一期的Spring Tips视频(在 YouTube 上)。

新的 AOT 引擎

这个版本最大的变化无疑是引入了新的 AOT 引擎,该引擎在构建时对 Spring 程序进行深入的转化和分析,并生成所需的 GraalVM Native 配置。这些转换由 Maven 和 Gradle Spring AOT 插件执行。


更深入地说,AOT 引擎在构建时评估构建环境,以便生成专门为您的应用程序优化后的 application context 和 Spring factories(Spring Boot 背后的插件系统)。在实践中,这意味着:


  • 在运行时执行的 Spring 基础结构更少

  • 在运行时要判断的条件更少

  • 减少反射,因为使用的是编程式bean注册


AOT 引擎根据标记为活动的 Bean、Spring 编程模型的知识以及与 Spring Native 捆绑在一起或由应用程序本身提供的 native hint,来推断出将应用程序编译为本机可执行文件所需的 native configuration。


我们要特别感谢 Stéphane Nicoll 领导了这个新的 AOT 引擎的设计和实现。

减少内存占用

AOT 引擎的一个关键优势是,基于它的原生可执行文件占用的内存更少,因为 native configuration 更准确,反射使用得更少,运行时需要的 Spring 基础结构更少。


Spring Native 0.11 与 Spring Native 0.10 相比,平均减少了 20%26% 的内存占用!下图显示了几个示例应用程序的数据:


启动速度更快

与 0.10 版本相比,Spring Native 0.11 的启动时间快了 16%35% ,因为某些处理逻辑已经从运行时转移到了编译时。Spring Boot 和 Spring Framework 的内部架构还有微调的空间,因此这部分仍有改进的余地。


兼容性改进

AOT 引擎也更加精确,因为它没有试图分析 Spring annotation 或其他类型信息来重复 Spring 在运行时所做的事情。相反,它 fork 一个新进程,在编译时创建并内省、探测 application context (在不启动应用程序的情况下)。这允许利用部分 Spring Framework 在运行时所做的工作,并在 bean 定义级别上工作,这比原来精确得多。

运行时的灵活性

在编译时执行这些优化意味着运行时灵活性低于常规的 Spring Boot 自动配置模型。例如,在运行已编译为原生二进制的 Spring Boot 应用程序时,仍然可以更改应用程序的 HTTP 端口或日志级别,但不能在运行时使用配置文件来添加新的 Bean。


这就是为什么在 JVM 上,AOT 模式仅仅是一种可选的运行模式,而不是唯一的运行模式。如果 AOT 符合您的需求,你就可以使用这种优化。在原生模式下(根据设计,此时运行时的动态性要低得多),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 模式的测试支持提升到一个全新的水平。让 Spring Native 兼容性显著提高,支持更多种类的测试。


结合Native构建工具,它允许您运行 Spring Boot,Spring Framework 或普通的 JUnit 测试,就像在 JVM 上一样。


与 Spring 无关,Mockito 目前还不支持支持,但目前 Mockito 开发者仍然在做类似的工作,以便 Mockito 将来能够在 AOT 模式下工作。

传统 JVM 上的 AOT

在将在 JVM 上运行的应用程序上执行 AOT 转换有两个关键好处。


第一个是能够轻松调试将在 IDE 中的 JVM(主应用程序或测试)上运行的代码。


第二个优点是效率更高。目前,它可以减少约 4%17% 的内存占用。



AOT 模式还将应用程序启动速度提高了 3%24%



请注意,到目前为止,我们还没有特别关注传统 JVM 上的 AOT 效率,因此在以后的版本中很可能有机会进行进一步改进。

Bellsoft Liberica NIK

Bellsoft Liberica Native Image Kit (NIK)是一个基于GraalVM开源代码和 Liberica JDK 的 Native Image 编译器发行版。从 Spring Native 0.11 开始,它默认用于 Buildpacks 的 native 模式,这与 JDK 模式一样,都默认使用 Liberica JDK。也可以通过使用SDKMAN安装或手动下载安装


今年早些时候,Buildpacks 团队宣布,使用 Liberica Native Image Kit 的 VMware 客户可以将其 Spring 应用程序作为原生可执行文件运行,并确认它们会得到完全的支持。

新的基线

Spring Native 0.11 也让我们有机会提供基于Spring Boot 2.6的新基线。


  • GraalVM 21.3提供了对 Java 11 和 Java 17 的支持,并利用有条件的Native 配置和其他相关的改进来允许占用更小的内存占用,并对 JVM 生态提供更好的 Native 模式支持。

  • 不再提供 Java 8 版本的 GraalVM,因为它太老了,无法进行合理的维护,但您仍然可以使用 Java 11 版本的 GraalVM 编译大多数 Java 8 应用程序。

  • 支持 Native Build Tools 0.9.8,我们将继续合作来完善和改进它。

Spring Boot 3 将原生支持 Native 模式

Spring Native 0.11 为 Spring Boot 提供了成熟的 Native 模式。Spring 团队现在可以专注于下一个主要步骤:作为 Spring Framework 6、Spring Boot 3 和相关组合项的一部分,改进 Native 模式的支持。


请记住,在 Spring Native 上所做的一切工作都是与其他 Spring 项目密切合作完成的,但没有进行深层的架构修改。随着 AOT 和 Native 模式成为 Spring Boot 3 和 Spring Framework 6 的主要主题,这些特性的质量、可维护性和易用性将达到一个新的水平。AOT 引擎将被改进并直接集成到 Spring 框架中。其他项目,比如 Spring Data 或 Spring Security,将能够在其范围内提供 Native 模式的支持(并对其进行测试),而 Spring Boot 将在其插件和文档中提供开箱即用的 AOT 和原生可执行文件支持。


我们与 GraalVM 团队和 JVM 生态的协作将会增加,以便为 Spring 之外的各种三方库提供 Native configuration,要么直接在那些三方库中,要么在 Native Build Tools 附带的 Native configuration 代码库中。


我们计划在 Spring Boot 3 milestone 2 版本开始提供开箱即用的 GraalVM Native 模式支持,预计在 2022 年 3 月下旬发布,并利用上在 Spring native 上的工作成果。Spring Boot 的 Native 模式计划于 2022 年底全面启用


Spring Native 有很多令人兴奋的计划,但现在,让我们花些时间与 Spring 社区的成员一起庆祝这个发布!


本文首发于 https://robberphex.com/new-aot-engine-brings-spring-native-to-the-next-level/ ,本文翻译自https://spring.io/blog/2021/12/09/new-aot-engine-brings-spring-native-to-the-next-level

用户头像

Robert Lu

关注

还未添加个人签名 2015.04.06 加入

阿里云高级开发工程师

评论

发布
暂无评论
Spring Native 0.11发布,带来新的AOT引擎和性能优化