写点什么

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

  • 2021 年 3 月 21 日
  • 本文字数:3349 字

    阅读完需:约 11 分钟

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:1416264
用户头像
张卫滨 业精于勤,行成于思。

发布了 425 篇内容, 共 245.1 次阅读, 收获喜欢 481 次。

关注

评论 2 条评论

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

阿里面经抢先看,助力重拿offer

Java小城向西看

Java 程序员 面试 社招 秋招

图文并茂!Github首发的这份阿里并发笔记(全彩),700页封神

欧子说Java

Java 编程 程序员 面试 Java技术提升

JVM性能调优都做了什么?阿里内网JVM虚拟机性能调优指南给出了答案

退休的汤姆

程序员 JVM 面经 社招 秋招

还能翻盘?京东3面失利,面试官却给份「Java指北面试PDF」叫我看

欧子说Java

Java 程序员 面试 面经 秋招

【TypeScript】TypeScript数据类型(上篇)

海底烧烤店ai

typescript 前端 8月月更

腾讯java岗3面凉凉后,狂刷这10套复习题顺利拿下阿里offer定级P7

tony带水

Java 编程 程序员 Java工程师 秋招

对标金九银十,阿里面试官甩出内部Java笔记,助我上岸

欧子说Java

Java 程序员 面试 面经 秋招

惊了!阿里P8自爆秋招面试核心手册,Github上获赞74.7K

Java魔鬼筋肉人

Java 面经 Java工程师 秋招 内推

史上最全的一篇微服务实战,终于有人把微服务架构讲清了!

tony带水

Java 编程 程序员 Java工程师 秋招

背废完虐面试官!字节架构师8年心血终成《图解设计模式》手册,拿下offer洒洒水啦

Java技术识堂

Java 面试题 面经 Java工程师 秋招

深入理解!阿里P8架构师手打300页高并发编程笔记,带你走出CRUD

欧子说Java

Java 程序员 面试 面经 秋招

字节顶级架构师保驾护航!国内首本大型分布式架构笔记浴火新生

欧子说Java

Java 程序员 面试 面经 秋招

并发量很大?阿里上传在GitHub的亿级流量百万并发手册爆火

退休的汤姆

Java 程序员 阿里 并发 秋招

阿里架构师总结Spring boot使用心得:全在这一份PDF文档里面了

tony带水

Java 编程 程序员 Java工程师 秋招

fastFFI 官宣开源,一款高效的Java跨语言通信框架

Java-fenn

Java 开源 java面试 秋招

阿里、腾讯、美团秋招真题“惨遭”泄露,Github上标星77.3K

Java魔鬼筋肉人

Java 面经 Java工程师 秋招 内推

SpringCloud微服务架构升级总结

java说

Java

一度霸占GitHub榜首!腾讯P8架构师手打800页微服务深度解析笔记

欧子说Java

Java 程序员 面试 微服务 秋招

12个yyds的低代码开源项目,一天开发一个系统!

杨哥说Java

Java 程序员

学透这份300页的2020最新java面试题及答案,让你成功定位阿里P8

tony带水

Java 编程 程序员 Java工程师 秋招

2020java春季面试指南一至五年必看:jvm+多线程+spring+微服务等

tony带水

Java 编程 程序员 Java工程师 秋招

华为2023届提前批预热开始!左 神的程序代码面试指南终派上用场

Java海

Java 程序员面试 大厂技能 秋招 程序代码面试指南

震惊!阿里自爆十万字Java面试手抄本,脉脉一周狂转60w/次

Java魔鬼筋肉人

Java 面经 Java工程师 秋招 内推

阿里P8总结出了java程序设计:从内存分析.JVM底层.数据结构PDF

tony带水

Java 编程 程序员 Java工程师 秋招

大厂福利内卷,35岁不再是条红线?DBA攻坚指南竟成最佳破冰手段

欧子说Java

Java 程序员 面试 面经 内卷

【TypeScript】TypeScript数据类型(下篇)

海底烧烤店ai

typescript 前端 8月月更

Spring 常犯的十大错误

java说

Java spring

分布式事务面试八股文(2022最新整理)

Geek_9b0de0

Java 开源 程序员 架构 面试

差点自闭!京东面试官夺命连环问操作系统,幸好最后拿到了 offer

Java技术识堂

Java 面试 校招 Java工程师 java秋招

秋招来临,当BAT大神总结出10W字BAT技术面小抄PDF,我完全不慌了

欧子说Java

Java 程序员 面试 面经 秋招

膜拜!阿里首次开源 Java 10万字题库,Github仅一天星标就超70K

Java魔鬼筋肉人

Java 面经 Java工程师 秋招 内推

Spring Native Beta正式发布,原生更香!_架构_Spring官方博客_InfoQ精选文章