Graph + AI 中国峰会火热报名中,点击探索图分析更多可能! 了解详情
写点什么

Spring Native Beta 正式发布,原生更香!

2021 年 3 月 21 日

Spring Native Beta正式发布,原生更香!

本文最初发表于Spring博客网站,由 InfoQ 中文站翻译分享。


最近,Spring 发布了Spring Native的 beta 版本,该功能已经在start.spring.io上可用了。


这意味着,除了 Spring 诞生以来就支持的 Java 虚拟机,官方添加了使用GraalVM将 Spring 应用编译成原生镜像的 beta 支持,这样的话,就能提供一种新的方式来部署 Spring 应用。Spring Native 支持 Java 和 Kotlin。


这些原生的 Spring 应用可以作为一个独立的可执行文件进行部署(不需要安装 JVM),并且还能提供有趣的特征,包括几乎瞬时的启动(一般会小于 100 毫秒)、瞬时的峰值性能以及更低的资源消耗,其代价是比 JVM 更长的构建时间和更少的运行时优化。



通过简单的mvn spring-boot:build-imagegradle bootBuildImage命令,就能生成一个优化的容器镜像,它包含了一个最小的操作系统层和一个小的原生可执行文件,该文件只包含了必需的东西即 JDK、Spring 以及应用中所使用的依赖。


请看下面这个最小的容器镜像,它是一个 50MB 的可执行文件,包含了 Spring Boot、Spring MVC、Jackson、Tomcat、JDK 和应用本身。



这种原生方式,在很多场景下都会对 Spring 应用产生价值:


  • 使用 Spring Cloud Function 的 Serverless 应用

  • 更廉价、更可持续地托管 Spring 微服务

  • VMware Tanzu这样的 Kubernetes 平台有很好的契合性

  • 想要最优的容器镜像,以打包 Spring 应用和服务


在使用场景上,比如 Piotr Mińkowski 提供了一个非常棒的指南,介绍了如何在Knative上使用 Spring Boot 和 GraalVM 构建原生微服务。

团队协作


Spring Native beta 是整个 Spring 团队及其家族项目广泛合作的结果:Spring Framework、Spring Boot 还包括 Spring Data、Spring Security、Spring Cloud 和 Spring Initializr。


据悉,原生功能的工作范围比 Spring 更广,因为原生涉及到更广泛的 JVM 生态系统,所以官方一直在与 GraalVM 团队合作,以改善原生镜像的兼容性和资源消耗。


以下是来自 GraalVM 团队的 Vojin Jovanovic 的一段话。


“与 Spring 团队协作打造原生 JVM 生态系统是一件非常愉快的事情:他们深厚的技术知识,再加上对社区的敏感触觉,总是能带来最好的解决方案。最新的 Spring Native 版本,以及它在 JVM 生态系统中的众多用法,为原生编译的广泛采用铺平了道路。”

支持的范围


现在,Spring Native 已经从 alpha 版本毕业成为 beta,那么很重要的一点就是明确它所支持的功能范围。


Alpha 版本是第一步,实验了很多东西,并且基于一组样例改善了 Spring Native(之前叫做 Spring GraalVM Native)的架构、兼容性和资源消耗,其中有很多破坏性的变更。官方还报告了很多问题,这些问题 GraalVM 团队已经解决,从而减少 JVM 和 Spring 应用的原生镜像之间的差距。


虽然它依然被认为是实验性的,但 beta 版意味着 Spring 现在在 Spring 生态系统的一个子集上提供了对原生的支持。如果你的应用正在使用业已支持的依赖,那么你可以试用它,在出现问题时可以提 bug 或贡献 pull request。在最新的 Spring Boot 2.x 小版本的每个补丁发布时,都会有一个新的 Spring Native 版本。Spring Native 0.9.0 支持 Spring Boot 2.4.3,Spring Native 0.9.1 将支持 Spring Boot 2.4.4 等。

start.spring.io


Stéphane Nicoll 在对start.spring.io和相关 IDE 的集成中,引入了对 Spring Native 的支持,所以现在这是探索如何使用 Spring 构建原生应用最简单的方式。



添加 Spring Native 依赖后将会使用所需的依赖和插件自动配置 Maven 或 Gradle 项目,以便于支持原生。应用代码本身没有变化。


请检查自动生成的HELP.md文件,该文件包含了有用的链接和文档,同时它还能标记出来你是否选择了一些在原生环境下不支持的依赖。

预先转换


原生与 JVM 有所不同:类路径在构建时是固定的,反射或资源需要进行配置,这里没有类的懒加载(可执行文件中包含的所有内容在启动的时候都会加载进来)并且有些代码可以在构建期调用。


为了充分拥抱这些特性,并且能让 Spring 应用以最大的兼容性和最小的资源消耗运行在原生环境中,Brian Clozel 在这个版本中引入了 Spring 预先(ahead-of-time,AOT)转换的 Maven 和 Gradle 插件,这个插件会对 Spring 应用执行预先转换。


第一种转换的目的是生成 GraalVM 原生配置(反射、资源、代理、原生镜像选项),这是通过由 Andy Clement 设计和实现的一个特别棒的推断引擎做到的,该引擎能够理解 Spring 编程模型和基础设施。例如,每个带有 @Controller 注解的类,都会在生成的 reflect-config.json 文件中添加一个条目。


有些原生配置是无法推断的,对于这些情况,Spring Native 引入了原生线索(native hint)注解(参见 Javadoc 以了解详情),这些注解允许 Spring Native 支持原生配置,这种方式比常规的基于 JSON 的原生镜像配置更加可维护、类型安全和灵活。例如,Spring Native 对 MySQL 驱动支持就提供了线索注解,它们会在原生镜像配置reflect-config.jsonresource-config.jsonnative-image.properties中生成正确的条目,如下所示:


@NativeHint(    trigger = Driver.class,    options = "--enable-all-security-services",    types = @TypeHint(types = {       FailoverConnectionUrl.class,       FailoverDnsSrvConnectionUrl.class,       // ...    }), resources = {    @ResourceHint(patterns = "com/mysql/cj/TlsSettings.properties"),    @ResourceHint(patterns = "com.mysql.cj.LocalizedErrorMessages",                      isBundle = true)})public class MySqlHints implements NativeConfiguration {}
复制代码


NativeConfiguration 和其他的动态配置机制允许实现更加强大和动态化的配置生成,但是需要注意它们的 API 在未来的版本中可能会有很大变化。


Spring 开发人员也可以直接在 @Configuration 或 @SpringBootApplication 类上添加应用特定的原生线索注解,例如,对于使用RestTemplateWebClient这样的编程 API 序列化一个Book类为 JSON:


@TypeHint(types = Book.class)@SpringBootApplicationpublic class WebClientApplication {    // ...}
复制代码


在使用预先转换系统时,最后一个,可能也是最强大的一个机制就是根据 Spring Boot 部署模型和 GraalVM 原生镜像特征所引入的封闭世界(closed-world)假设,它能够自动生成针对原生环境进行优化的代码。这里的目标就是限制所需的外部原生配置的数量,从而提高兼容性,这是通过原生镜像编译器对代码结构的分析实现的,同时还能通过减少反射、资源或代理所需的配置,降低资源占用。一个具体的例子就是对各种spring.factory(Spring Boot 背后的扩展机制)的预先转换,从而实现一个优化过的程序版本,该版本不需要反射并且会过滤掉应用上下文中不必要的条目。


对 Spring AOT 来说,这只是一个开始,我们计划添加更加强大的转换,比如将@Configuration替换为函数式配置,从而通过预先分析替换运行时反射,能够自动生成使用像 lambda 表达式和方法引用这种程序构造的配置类。这样的话,就能允许 GraalVM 原生镜像编译器立即理解 Spring 配置,无需任何的反射配置或*.class资源。


需要记住的一个关键点是,在使用 Spring Native 时,这个 AOT 生成的代码在 JVM 上也会默认使用,这样的话能够通过 JVM 允许的短反馈循环(short feedback loop),用调试器和所有常规工具实现“原生友好的代码路径”。


尽管 Spring AOT 转换目前主要是由原生场景需求驱动,但是有很多转换并不是特定于原生场景的,有一些可能为 JVM 上运行的 Spring Boot 应用提供优化。和往常一样,对于这种主题,重要的是要以数据为驱动,所以我们会衡量效率和性能来驱动我们的决策。


我们很可能会完善 IDE 集成,目前请务必阅读相关文档,了解潜在的手动配置步骤,以便在 IDE 中运行应用程序之前更新生成的源码。

结论

在支持原生方面,Spring 有两个支柱性的策略。第一个是在不需要对现有的数百万个 Spring Boot 应用进行重大改动的情况下,对 Spring 基础架构进行调整以适应原生。这包括在 Spring 顶层项目中为实现原生友好而做出的改变,像 @NativeHint 这样的基础架构,以及在 Spring Native 中逐渐成熟的 Spring AOT 构建插件。


第二个支柱比 Spring 本身的范围更广,原生是一个与 JVM 特性有所差异的平台,但 Java 生态系统需要尽可能地保持一致,以避免出现两种截然不同的 Java 风格,如果这样的话,将会是维护上的一个挑战。


原文链接:


https://spring.io/blog/2021/03/11/announcing-spring-native-beta


相关推荐:


中国顶尖技术团队访谈录(2021年第一季)

2021 年 3 月 21 日 12:1414625
用户头像
张卫滨 业精于勤,行成于思。

发布了 387 篇内容, 共 224.0 次阅读, 收获喜欢 361 次。

关注

评论 2 条评论

发布
用户头像
特性很吸引人
2021 年 03 月 29 日 13:54
回复
用户头像
这个好。这也是为了应对云原生时代其他语言的冲击,而做出的改变。
2021 年 03 月 29 日 11:37
回复
没有更多了
发现更多内容

SICP 习题解答 1.10

十元

Vue3源码 | 深入理解响应式系统上篇-reactive

梁龙先森

前端 Vue3 源码解析

真香!阿里大牛“亲码”千页Redis源码笔记,差距不止一点点

程序员小毕

Java redis 源码 架构 面试

Docker 教程(一):Docker 是什么

看山

Docker DevOps

学习曾国藩:职场咸鱼的翻身之法

boshi

七日更 职业生涯

SICP 习题解答 1.8

十元

第一章-认识产品经理作业

阿珍爱上阿强

产品经理 JD 财务

迷宫算法(DFS)

大忽悠

3月日更

laravel的生命周期

一个大红包

28天挑战 3月日更

第五次作业&总结

青葵

学习

一个程序员应怀揣武侠梦

DisonTangor

程序员

SICP 习题解答 1.7

十元

浅谈微服务架构

跳蚤

Prometheus+SpringBoot应用监控全过程详解

程序员小毕

Java 源码 程序员 面试 springboot

程序员成长第二十二篇:做任务分配时,要考虑员工的成长。

石云升

项目管理 程序员 28天写作 职场经验 3月日更

SICP 习题解答 1.9

十元

android面试!Android事件体系全面总结+实践分析,大牛最佳总结

欢喜学安卓

android 程序员 面试 移动开发

恋物志(三):“美丽到牙齿”的智能硬件圈地运动

脑极体

python常用库简介

张鹤羽粑粑

28天写作 3月日更

Wireshark数据包分析学习笔记Day4

穿过生命散发芬芳

Wireshark 数据包分析 3月日更

【自动化】Day01

IT蜗壳

需要深入的技术领域,方向正确是成功的关键

杨明越

设计模式的5个常见问题及解决办法

乐天

设计模式

前端抱怨API响应慢,我们后端该做些什么?

程序员小毕

源码 程序员 面试 后端 API

开课啦基于 dubbo-go 的服务端技术升级实战

apache/dubbo-go

微服务 云原生 dubbo dubbo-go dubbogo

《撬动星球的头部效应-绝非偶然》读书笔记

SilentMacUser

极客时间 读书笔记 产品经理 知识星球 极客大学产品经理训练营

面试官:小伙子你给我说说MySql并发事务处理细节

程序员小毕

Java MySQL 程序员 面试 事务

ARTS - week 1

steve_lee

人生如戏,戏如人生——敏捷剧本杀玩后感

Bruce Talk

敏捷 Agile

Android入门你值得拥有!手持4个大厂offer的我,附面试题答案

欢喜学安卓

android 程序员 面试 移动开发

LinqToExcel.Extend 源码分析

happlyfox

28天写作 3月日更

Spring Native Beta正式发布,原生更香!-InfoQ