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

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插件执行。

spring boot native

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

  • 在运行时执行的 Spring 基础结构更少
  • 在运行时要判断的条件更少
  • 减少反射,因为使用的是编程式bean注册

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

aot architecture

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

减少内存占用

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

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

native rss

启动速度更快

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

native startup

兼容性改进

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 提前创建一个类代理:

1
2
3
4
5
6
7
8
9
10
11
12
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:

1
2
3
4
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% 的内存占用。

jvm rss

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

jvm startup

请注意,到目前为止,我们还没有特别关注传统 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和原生可执行文件支持。

boot3 aot architecture

我们与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://spring.io/blog/2021/12/09/new-aot-engine-brings-spring-native-to-the-next-level

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

https://robberphex.com/new-aot-engine-brings-spring-native-to-the-next-level/

作者

Robert Lu

发布于

2021-12-12

许可协议

评论