今天,经过一年半的努力,我很高兴地宣布,我们将推出Spring Native的测试版,并在 start.springboot.io 上提供服务!
实际上,这意味着除了Spring自成立以来所支持的常规Java虚拟机之外,我们还增加了测试版支持将Spring应用编译成GraalVM的本地镜像,以提供一种新的方式来部署Spring应用。支持Java和Kotlin。
这些原生Spring应用可以作为独立的可执行文件进行部署(无需安装JVM),并提供了有趣的特性,包括几乎即时启动(通常<100ms)、即时峰值性能和更低的内存消耗,但代价是比JVM更长的构建时间和更少的运行时优化。
通过简单的mvn spring-boot:build-image
或gradle bootBuildImage
命令,你可以生成一个优化的容器映像,它将包含一个最小的操作系统层和一个小的本地可执行文件,这些文件只包含JDK、Spring和你在应用中使用的依赖关系中所需要的部分。请看下面的例子,一个最小的容器映像,包含50MB的可执行文件,其中包含Spring Boot、Spring MVC、Jackson、Tomcat、JDK和应用程序。
在广泛的用例中,原生应用对您的Spring应用是有意义的:
- 利用Spring Cloud功能实现无服务器化
- 为您的Spring微服务提供更便宜、更可持续的托管服务。
- 与VMware Tanzu等Kubernetes平台有很好的契合度。
- 想要创建包装您的Spring应用和服务的最佳容器图像吗?
我相信神奇的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团队解释我们如何构建Spring Native测试版以及它所提供的功能,包括演示全新的 start.springboot.io 支持。
(视频需要科学上网:https://youtu.be/96n_YpGx-JU)
我们的原生工作范围比Spring更广,因为原生涉及到更广泛的JVM生态系统,所以我们一直在与GraalVM团队合作,以改善原生镜像的兼容性和足迹。以下是来自GraalVM团队的Vojin Jovanovic的一段话。
与Spring团队合作打造原生JVM生态系统是一件非常愉快的事情:他们深厚的技术知识,加上对社区的敏感触觉,总是能带来最好的解决方案。最新的Spring Native版本,以及它在JVM生态系统中的众多用法,为原生编译的广泛采用铺平了道路。
支持的范围
随着Spring Native从alpha毕业到beta,我认为澄清我们提供的支持范围很重要。
Alpha是第一步,我们做了很多实验,并在一组样本上完善了Spring Native(之前名为Spring GraalVM Native)的架构、兼容性和足迹,有很多突破性的变化。我们也报告了很多问题,GraalVM团队修复了这些问题,以减少Spring应用的JVM和原生之间的差距。
虽然它仍然被认为是实验性的,但测试版意味着Spring现在在Spring生态系统的一个子集上提供了对原生的支持。你可以在你的项目上试用它,如果它们正在使用支持的依赖,并在出现问题时提出bug或贡献pull请求。在最新的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等。突破性的变化会发生,但我们会记录迁移路径。文档质量已经达到了一个新的水平:参考文档以html单页或pdf的形式提供,我们发布了本地提示公共API的Javadoc。
start.springboot.io
Stéphane Nicoll 已经在 start.springboot.io 上引入了对Spring Native的支持,以及相关的IDE集成,所以从今天起,这可能是探索如何用Spring构建原生应用的最简单方法。
添加Spring Native依赖关系会自动为你的Maven或Gradle项目配置所需的依赖关系和插件以支持原生。应用程序代码本身没有变化。
请务必检查生成的HELP.md
文件,其中包含有用的链接和文档,但也会提示你是否选择了一些已知不支持native的依赖关系。
时间前的转变
原生与JVM不同:在构建时classpath是固定的,比如反射或资源需要配置,没有类的懒惰加载(可执行文件中运来的所有东西都在启动时加载在内存中),一些代码可以在构建时被调用。
为了充分体现这些特性,让Spring应用以最大的兼容性和最小的占用率运行在原生上,Brian Clozel在这个版本中引入了Spring超前时间(AOT)Maven和Gradle插件,对你的应用进行超前时间转换。
第一种转换打算基于神奇的Andy Clement设计和实现的推理引擎生成GraalVM原生配置(反射、资源、代理、原生映像选项),它了解什么是Spring编程模型和基础设施。例如,每一个被@Controller
注解的类,都会在生成的reflect-config.json
文件中添加一个条目。
有些原生配置无法推断,对于这些情况,我们将引入原生提示注释(更多细节请参见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)
@SpringBootApplication
public class WebClientApplication {
// ...
}
最后一个,也可能是在使用超前转换系统时最强大的机制,就是利用Spring Boot部署模型引入的封闭世界假设,结合GraalVM原生镜像特性,自动生成原生优化代码(源码和字节码)的能力。这里的目标是通过使用可以被原生映像编译器开箱分析的代码构造来限制所需的额外原生配置量以提高兼容性,并通过减少反射、资源或代理所需的配置量来降低足迹。一个具体的例子就是将各种 spring.factories
(Spring Boot背后的扩展机制)提前转化为优化的程序化版本,不需要反射,并且在你的应用上下文中过滤掉不必要的条目。
这只是Spring AOT的一个开始,我们打算给功能配置添加更强大的转换,比如@Configuration,通过超前分析来取代运行时反射,自动生成配置类,使用lambdas和方法引用等程序化构造。这将使GraalVM原生映像编译器能够开箱即用地理解Spring配置,而不需要任何反射配置或*.class
资源。
需要注意的一个关键点是,当使用Spring Native时,这个AOT生成的代码在JVM上也是默认使用的,以便让你通过JVM允许的短反馈循环,用你的调试器和所有常规工具行使 “原生友好的代码路径”。
虽然Spring AOT转换目前主要是由原生需求驱动的,但很多都不是针对原生的,有可能有些可以为在JVM上运行Spring Boot应用提供优化。和往常一样,对于这种主题,重要的是要以数据为驱动,所以我们会衡量效率和性能来驱动我们的决策。
我们很可能会完善IDE集成,目前请务必阅读相关文档,了解潜在的手动配置步骤,以便在IDE中运行应用程序之前更新生成的源。
结束语
在Spring的原生战略中,有两个主要支柱。第一个是在不需要对现有的数百万个Spring Boot应用进行重大改变的情况下,对Spring基础设施进行适应原生的调整。这包括我们在Spring顶层项目中做出的对原生友好的改变,像@NativeHint
这样的基础架构以及我们在Spring Native中成熟的Spring AOT构建插件。查看我们的路线图,了解更多关于即将到来的步骤的信息。
第二个支柱比Spring本身的范围更广,原生是一个与JVM不同特性的平台,但Java生态系统需要尽可能保持一致,以避免两种截然不同的Java风味,这将是维护的挑战。这就是为什么我们与GraalVM团队进行深入合作,以减少这种差距。在接下来的几个月里,这种合作将专注于为更广泛的JVM生态系统改进原生测试和原生配置。
Spring开发者可以通过我们提供的各种样本了解更多关于原生的信息,上 start.springboot.io 测试我们新的原生支持,阅读更新后的参考指南,阅读发布说明,尤其是当你从以前的版本升级时,甚至可以为你喜欢的依赖关系贡献支持。如果你想了解更多相关Spring商业支持的信息,也可以联系我们。
最后,我将对已经提供了大量有用反馈和贡献的Spring社区,对GraalVM团队的这次惊人合作,以及为Spring开发者更容易地采用原生技术而努力工作的广大Spring团队表示感谢。
原文:https://spring.io/blog/2021/03/11/announcing-spring-native-beta