Spring干掉原生JVM?

spring 团队日前发布了 spring native beta 版。通过 spring native,spring 应用将有机会与 graalvm 原生镜像的方式运行。为了更好地支持原生运行,spring native 提供了 maven 和 gradle 插件,并且提供了优化原生配置的注解。
最近,spring 发布了 spring native 的 beta 版本,该功能已经在 start.spring.io 上可用了。
https://github.com/spring-projects-experimental/spring-native
https://start.spring.io/
这意味着,除了 spring 诞生以来就支持的 java 虚拟机,官方添加了使用 graalvm 将 spring 应用编译成原生镜像的 beta 支持,这样的话,就能提供一种新的方式来部署 spring 应用。spring native 支持 java 和 kotlin。
这些原生的 spring 应用可以作为一个独立的可执行文件进行部署(不需要安装 jvm),并且还能提供有趣的特征,包括几乎瞬时的启动(一般会小于 100 毫秒)、瞬时的峰值性能以及更低的资源消耗,其代价是比 jvm 更长的构建时间和更少的运行时优化。
通过简单的 mvn spring-boot:build-image 或 gradle 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 构建原生微服务。
https://piotrminkowski.com/2021/03/05/microservices-on-knative-with-spring-boot-and-graalvm/
1. 团队协作 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 boot + mybatis plus + vue & element 实现的后台管理系统 + 用户小程序,支持 rbac 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/yunaiv/ruoyi-vue-pro 视频教程:https://doc.iocoder.cn/video/ 2. 支持的范围 现在,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 等。
基于 spring cloud alibaba + gateway + nacos + rocketmq + vue & element 实现的后台管理系统 + 用户小程序,支持 rbac 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/yunaiv/yudao-cloud 视频教程:https://doc.iocoder.cn/video/ 3. start.spring.io stéphane nicoll 在对 http://start.spring.io 和相关 ide 的集成中,引入了对 spring native 的支持,所以现在这是探索如何使用 spring 构建原生应用最简单的方式。
添加 spring native 依赖后将会使用所需的依赖和插件自动配置 maven 或 gradle 项目,以便于支持原生。应用代码本身没有变化。
请检查自动生成的 help.md 文件,该文件包含了有用的链接和文档,同时它还能标记出来你是否选择了一些在原生环境下不支持的依赖。
4. 预先转换 原生与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.json、resource-config.json 和 native-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 类上添加应用特定的原生线索注解,例如,对于使用 resttemplate 或 webclient 这样的编程 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 中运行应用程序之前更新生成的源码。
5. 结论 在支持原生方面,spring 有两个支柱性的策略。第一个是在不需要对现有的数百万个 spring boot 应用进行重大改动的情况下,对 spring 基础架构进行调整以适应原生。这包括在 spring 顶层项目中为实现原生友好而做出的改变,像 @nativehint 这样的基础架构,以及在 spring native 中逐渐成熟的 spring aot 构建插件。
第二个支柱比spring本身的范围更广,原生是一个与 jvm 特性有所差异的平台,但 java 生态系统需要尽可能地保持一致,以避免出现两种截然不同的 java 风格,如果这样的话,将会是维护上的一个挑战。


莱尔德推出CM6050 系列DC/DC电源线共模扼流圈
新能源汽车市场下滑 二手车市场也极其尴尬
投影电视怎么操作_投影电视的特点
华为Mate40E详细规格配置曝光
二极管的的定义及主要参数
Spring干掉原生JVM?
中国移动积极推进边缘计算产业的商用落地和生态构建
纵行科技入围2022年度中国“高成长未来独角兽企业榜”
应对5G需求 ARM将调整处理器架构设计
SDR--未来无线通信设备的基本概念
华明FJK-1型漏电断路器原理分析
我国共有18.5万家企业名称或经营范围含“机器人”
AI服务器与传统服务器的区别是什么?
采用ADS7846控制器的电阻式触摸屏接口电路设计
ZNS SSD设计架构及性能优化
移动机器人的应用落地将会面临哪些挑战
安森美半导体的LDO稳压器系列简介
中央空调远程运维监控控制方案
十年紧密合作,华为与润和共同见证彼此的成长历程 重心转到AI等方面
西部数据18TB和20TB机械硬盘开始出样 明年下半年将大规模量产出货