通过本篇文章您可以了解到以下内容:
- Spring Native 简介
- Spring Native 深入剖析
- 总结
Spring Native 简介
当我们看到 Spring Native 这个词语的时候,是不是会有诸多疑问? 比如什么是 Spring Native,它是用来解决什么问题的? 它和我们现在已经熟知的 Spring Boot 以及 Spring Cloud 又有什么联系呢?
接下来就让我们带着这些疑问走进今天的文章,为您揭开 Spring Native 的面纱。
首先让我们看看什么是 Spring Native?
中文:
Spring Native 可以使得 Spring 应用程序以 GraalVM 原生镜像的方式进行运行。
与 Java 虚拟机相比,native image 可以为许多类型的工作负载提供更经济、更可持续的托管。这些包括微服务、非常适合容器的功能工作负载和 Kubernetes。
使用 native image 这种方式具备一些关键优势,如即时启动、即时峰值性能和减少内存消耗。
Spring Native 的诞生意味着 Spring 除了支持常规的 Java 虚拟机以外,还可以支持使用 GraalVM 原生镜像的方式进行运行。从而提供了一种新的部署 Spring 应用程序的方法。
该项目的目标是孵化对 Spring Native(Spring JVM 的替代品)的支持,并提供旨在打包到轻量级容器中的本机部署选项。实际上,目标是在这个新平台上支持您的 Spring 应用程序,而对代码层面是几乎没有修改的。同时Spring Native 支持 Java 和 Kotlin。
令人鼓舞的是 Spring Native 项目是整个 Spring 团队及其家族项目广泛合作的结,例如我们众所周知的 Spring Framework、Spring Boot 以及 Spring Data、Spring Security、Spring Cloud 等。
既然 Spring Native 支持以 GraalVM 原生镜像的方式运行,那么相比于 JVM 方式它的优点又有哪些呢?
概括起来可以理解为两大方面,分别是对资源的消耗(内存)的减少以及应用启动时间的缩短。
而对于应用启动时间来说,可以理解为即时启动(通常的情况下时间小雨 100ms),如下图所示,基于 Spring Boot 的 Web 应用的简单例子,启动时间仅为 0.038s。
在介绍完 Spring Native 的定义以及相比 JVM 的优势以后,接下来让我们看看 Spring Native 都有哪些模块组成:
spring-native
运行 Spring Native 所需的运行时依赖项,还提供了本机 hints API。
spring-native-configuration
Spring AOT 插件使用的 Spring 类的配置提示,包括各种 Spring Boot 自动配置。
spring-native-docs
Spring 原生文档,参考指南,采用 asciidoc 格式。
spring-native-tools
spring 原生工具:用于查看映像构建配置和输出的工具。
spring-aot
Maven 和 Gradle 插件公共的 aot 转换基础架构。
spring-aot-test:
测试特定的 AOT 基础架构。
spring-aot-gradle-plugin 和 spring-aot-maven-plugin
顾名思义,AOT 转换的 gradle 和 maven 的插件
samples
包含各种示例,演示特性的使用,并用作集成测试。
通过上述的介绍,我们清楚了 Spring Native 的定义以及相比传统 JVM 的优势、同时了解了该项目包含了哪些模块。那么我们该如何尝试使用 Spring Native 在我们的项目中呢?
在 start.spring.io 中提供了快速集成创建基于Spring Native 的方法,只需要添加相关 Native 的依赖即可。如下图所示:
值得注意的是对于 Spring Native 给出的标签是 DEVELOPER TOOLS。如果把 Spring Boot 比作一辆汽车的话,那么对于 JVM 运行的这种方式可以比作汽车的发动机引擎,而 Spring Native 的出现,正好是对现有的汽车在选择发动机引擎时多了一种解决方案。
在对 Spring Native 有个初步认知以后,接下来让我们深入的了解下 Spring Native 背后的故事。
Spring Native深入剖析
在上一小节中,我们谈到了基于 GraalVM native image 的优势(例如启动时间快速,内存资源占用少等),接下来让我们看下 Native image 与传统常规的 JVM 的主要区别有哪些:
- 在构建时从主入口点对应用程序进行静态分析。
- 未使用的零件将在构建时被移除。
- 反射、资源和动态代理需要配置。
- 类路径在构建时是固定的。
- 无类延迟加载,可执行文件中的所有内容都将在启动时加载到内存中。
- 一些代码将在构建时运行。
- Java 应用程序的某些方面存在一些不完全支持的限制。
对于使用 native image 方式时,它的整个流程如下图所示:
Native Image 是一种将 Java 代码提前编译为独立可执行文件的技术,执行文件包括应用程序类、依赖、运行时库以及 JDK 静态连接的本机代码。Graalvm 通过子模块 SubstrateVM 来支持 Native Image。
JDK 字节码、对应的应用程序、第三方库类库共同组成了静态编译的输入,此时 SubstrateVM 会对输入进行静态的分析,并找到其中可达代码,然后可达代码将会有静态编译器进行编译,最终得到 native image。
在上面描述的整个流程中,Spring Native 所适配的方面分为两部分,分别是:
- 生成应用程序上下文的优化版本
- 根据需要推断元数据
看到这里,相信大家都会发现一个问题,那就是与传统的 JVM 不同的是,类路径在构建时已经是固定的,反射或资源需要进行配置,这里没有类的懒加载机制(可执行文件中包含的所有内容在启动的时候都会加载进来)并且有些代码可以在构建期调用。
为了充分拥抱这些特性,并允许 Spring 应用程序在本机上以最大的兼容性和最小的占用空间运行,Brian Clozel 引入了 Spring 预先(ahead-of-time,AOT)转换的 Maven 和 Gradle 插件,这个插件会对 Spring 应用执行预先转换。
第一种转换旨在基于推理引擎生成 GraalVM 本机配置(反射、资源、代理、本机映像选项)对于一些本机配置无法推断的情况,我们引入了本机提示注释(更多详细信息,请参阅 Javadoc),它允许 Spring native 以比常规基于 JSON 的本机映像配置更可维护、类型安全和灵活的方式支持本机配置。例如如下配置:
总结
回顾全篇内容,整体包括以下内容:
- 首先在 Spring Native 简介中,我们了解到了什么 Spring Native,同时介绍了所具备的优势又有哪些,此外还列举了 Spring Native 所包含的模块,并对其进行说明。
- 其次在 Spring Native 深入剖析中,我们与传统 JVM 方式进行了区别点的分析,接着介绍了关于 native image 构建的流程说明,最后介绍了 Spring 在其中做的内容又是哪些。
参考链接:
1.http://docs.spring.io/spring-native/docs/current/reference/htmlsingle/#overview
2.https://spring.io/blog/2021/03/11/announcing-spring-native-beta
内容来源|公众号:VMwareTanzu 云原生