走进Spring Boot 3.x时代(二)

目录

  • 前言

  • Spring Boot 3.2.0系统要求
  • Spring Boot 3.2.0 新特性和改进
  • Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈
  • 使用 Spring 和 GraalVM 原生镜像优化容器部署
  • JVM 检查点恢复:利用 Spring 和 CRaC 项目实现零扩展
  • 通过 Spring AOT 和 Project Leyden 一窥 OpenJDK 的未来
  • 结论

前言

        上篇文章介绍了Spring Boot 2.x到3.x的一些情况,并对Spring Boot 3.0做了一些新特性说明。本文主要描述对Spring Boot3.2.0新版本中新特性和改进内容。

Spring Boot 3.2.0系统要求

  • Java 17+,兼容Java21;
  • Spring Framework 6.1.1+;
  • Maven 3.6.3+;
  • Gradle 7.5+;

Spring Boot 3.2.0 新特性和改进

  1. 支持虚拟线程:Spring Boot 3.2 引入了对虚拟线程的支持,使得开发者可以在单个 JVM 上运行多个线程,从而提高应用程序的并发性能。
  2. 对 JVM Checkpoint Restore(Project CRaC)的初始支持:CRaC 是一个用于实现 JVM 状态恢复的项目,Spring Boot 3.2 提供了对 CRaC 的初始支持,使得开发者可以更方便地在发生故障时恢复应用程序的状态。
  3. SSL 捆绑包重新加载:Spring Boot 3.2 改进了 SSL 捆绑包的重新加载机制,使得在更改证书或密钥文件时,无需重启应用程序即可使更改生效。
  4. 大量可观测性改进:Spring Boot 3.2 对可观测性进行了大量改进,包括对 Micrometer、Prometheus、Zipkin 和 Jaeger 等流行监控和追踪工具的支持。
  5. 对 RestClient 的支持:Spring Boot 3.2 提供了对 RestClient 的支持,使得开发者可以更方便地调用其他微服务的 API。
  6. 对 JdbcClient 的支持:Spring Boot 3.2 提供了对 JdbcClient 的支持,使得开发者可以更方便地调用数据库操作。
  7. 支持 Jetty 12:Spring Boot 3.2 支持 Jetty 12,这是一个高性能的 HTTP 服务器和客户端库。
  8. 支持 Spring for Apache Pulsar:Spring Boot 3.2 提供了对 Spring for Apache Pulsar 的支持,使得开发者可以更方便地构建基于 Pulsar 的消息队列应用程序。
  9. 对 Kafka 和 RabbitMQ 的 SSL 捆绑包支持:Spring Boot 3.2 改进了对 Kafka 和 RabbitMQ 的 SSL 捆绑包的支持,使得在与这些消息队列服务进行通信时,可以使用加密连接。
  10. 重新设计了嵌套 Jar 处理:Spring Boot 3.2 对嵌套 Jar(Nested Jar)的处理进行了重新设计,解决了在某些情况下可能出现的问题。
  11. Docker 映像构建改进:Spring Boot 3.2 对使用 Maven 和 Gradle 构建的应用程序的 Docker 映像构建进行了改进,提高了构建速度和可靠性。

走进Spring Boot 3.x时代(二)_第1张图片

Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈

        虚拟线程(Virtual Threads)旨在降低以简单、流行的每请求线程方式编写的服务器应用程序的成本,以接近最佳的硬件利用率进行扩展。
         虚拟线程降低了 I/O 阻塞的成本,因此非常适合 Servlet 栈上的 Spring Web MVC 应用程序。通过虚拟线程设置,Spring MVC 可以在 Tomcat 或 Jetty 等平台上充分利用这些新的运行时特性。在大多数用例中,这不需要修改代码,就能自然地提供最佳性能,而无需对线程池配置进行微调。

        在 Spring Framework 6.1 中引入一个名为 RestClient 的 "虚拟线程友好型现代 HTTP 客户端"(Spring Cloud Gateway 和 Spring 产品组合中的相关基础架构同样可以从虚拟线程设置和 Spring MVC 中受益,从而提供一致的整体体验。

        那么,这对 WebFlux 和反应堆栈意味着什么呢?
        我们特意选择了不同的阻塞堆栈和反应堆栈,以充分利用 WebFlux 服务器中的反应优势,并尽可能精简 Spring Web MVC 堆栈(start.spring.io 上迄今为止最常用的 Web 堆栈)和常规阻塞线程架构。

  • Servlet 容器上的 Spring MVC 是虚拟线程的理想定位,是提高传统网络应用程序可扩展性的理想解决方案。
  • 另一方面,WebFlux 服务器提供了优化的反应式堆栈,非常适合 Netty I/O 设置,通过不同的编程模型提供同等的运行时优势。

当您需要应用级并发(例如,发送多个远程 HTTP 请求(可能是流式请求)并合并结果)时:

  • WebFlux 和 Reactor 等反应式 API 目前具有无可比拟的附加值,
  • Kotlin 的 Coroutines 及其 Flow 类型也具有无可比拟的附加值,它们提供了命令式和声明式编程模型的有趣组合。
  • RSocket 是反应式交互模型带来巨大附加值的另一个例子。

        请注意, Spring MVC 也提供可选的反应式支持。

        因此,如果您只需要在服务器应用程序中的几个用例中处理并发性问题,您可以简单地使用带有虚拟线程设置的 Spring MVC 堆栈,并在 Web 控制器中无缝地包含反应式 WebClient 交互,Spring MVC 会将反应式返回值调整为 Servlet 异步响应。

        Spring MVC 中的这种反应式支持完全是可选的,只有在实际使用反应式端点时才需要在堆栈中使用 Reactor 和 Reactive Streams,而且 HTTP 堆栈要基于 Servlet 容器,如 Tomcat 或 Jetty(而不是 Netty)。

        对于典型的网络Web场景,我们预计虚拟线程将成为 Spring MVC 的常见选择,成为 Java 21+ 的 Spring 开发人员的Web服务器栈。

        请确保使用 Spring Boot 3.2 或更高版本,将属性 spring.threads.virtual.enable 设置为 true,并使用最新的库和驱动程序版本来评估虚拟线程。

使用 Spring 和 GraalVM 原生镜像优化容器部署

        我们将继续完善 Spring Boot 3 中引入的 GraalVM 本机支持。主要用例是使用 Buildpacks 构建优化的容器映像,其中包含一个微小的操作系统基础层,以及通过 Spring AOT(Ahead Of Time)转换和 GraalVM 本地映像编译器编译为本地可执行文件的应用程序。无需分发 JVM。

        这样就可以部署在几十毫秒内启动的小型容器(通常比普通 JVM 的启动时间快 50 倍),降低应用基础架构的内存消耗,并立即实现峰值性能。

        GraalVM 紧跟 Java 的新特性,例如已经提供了一流的虚拟线程支持:请参阅 Josh Long 最近发表的博文《 All together now》。

        与 JVM 相比,GraalVM 的出色运行特性得益于不同的权衡取舍。本地镜像编译需要几分钟而不是几秒钟。它需要额外的元数据才能正确处理反射、代理和 JVM 的其他动态行为。Spring 会推断出很多此类元数据,但任何实际项目都可能需要一些额外的提示才能正常运行(例如,对于组织依赖关系)。最后,Spring AOT 转换和 GraalVM 原生镜像的结合要求我们在构建时冻结类路径和 Spring Boot Bean 条件。您通常可以在运行时配置中更改数据库的 URL 或密码,但不能更改数据库类型或更改 Spring Bean 的结构。

        从历史上看,另一个缺点是由于缺乏即时编译而导致峰值性能有限。

        有了即时启动和立即可用的峰值性能,Spring Boot 本机应用程序就能实现零扩展。

缩放为零

        缩放为零是对无服务器的一种概括。工作负载不仅可以部署到无服务器云平台,还可以部署到任何提供在没有请求要处理时向零扩展能力的 Kubernetes 或云平台。通过 Kubernetes,您可以使用 Knative 或 KEDA 等解决方案来实现零扩展。

        而且,你并不局限于函数,你可以将任何类型的应用程序、任何类型的编程模型(包括传统的网络应用程序)扩展到零。无服务器最重要的特点不在于技术,而在于它所实现的 "即用即付 "计费模式。

        在各种用例中,扩展到零可能会很有趣。JVM 在开发大流量网站方面表现出色,但老实说,我们也开发了许多小型后台应用程序,这些应用程序通常不会一直使用。既然没人使用,我们为什么还要付费呢?还有一些暂存环境,它们通常只需要运行一小部分时间,还有一些微服务,缓存允许在大部分时间关闭其中的几个。还有高可用性,它迫使我们为每个服务维护两个实例,以备不时之需,因为我们的应用程序启动时间太长,无法从危险中恢复。

        但是,对于那些无法接受 GraalVM 原生镜像所要求的权衡的项目来说,如何将其扩展为零呢?

JVM 检查点恢复:利用 Spring 和 CRaC 项目实现零扩展

        CRaC 是一个 OpenJDK 项目,它定义了一个新的 Java API,允许您在 HotSpot JVM 上检查点和还原应用程序,该项目由 Azul Systems 开发,同时也得到 AWS Lambda 和 IBM OpenLiberty 的支持。它基于在 Linux 上实现检查点/还原功能的 CRIU 项目。

        其原理如下:您几乎像往常一样启动应用程序,但使用的是启用了 CRaC 的 JDK 版本。然后在某个时间点,可能是在执行了所有常用代码路径而导致 JVM 发热的某些工作负载之后,使用 API 调用、jcmd 命令、HTTP 端点或其他机制触发检查点。

        然后,运行中的 JVM 的内存表示(包括其热度)会被序列化到磁盘上,这样就可以在稍后的时间点(可能是在具有类似操作系统和 CPU 架构的另一台机器上)快速恢复。恢复后的进程保留了 HotSpot JVM 的所有功能,包括运行时的进一步 JIT 优化。
        

        有趣的是,"检查点 "和 "恢复 "与 Spring 应用上下文生命周期的停止和启动阶段非常匹配。

        Spring Framework 6.1 的 CRaC 支持主要是将 CRaC 和 Spring 生命周期映射到一起,其他支持与 CRaC 无关,主要是对 Spring 生命周期的完善,旨在正确关闭和重新创建套接字、文件和池。除了常规的启动和停止生命周期外,这里的目标是支持多个停止和重启周期。

        与 GraalVM 一样,Project CRaC 允许应用程序从零扩展到零,即使在小型服务器上也能在几十毫秒内瞬间启动。这比普通 JVM 冷启动快 50 倍,与 GraalVM 本机镜像类似。但是,让我们来探讨一下其中的利弊得失。

        请记住,我们正处于 CRaC 项目的早期阶段,Spring Boot 3.2 是支持 CRaC 的第一个版本。随着检查点还原技术和 Spring 支持的发展,其中一些限制可能会被取消。

通过 Spring AOT 和 Project Leyden 一窥 OpenJDK 的未来

        我们已经看到了通过 GraalVM 和 CRaC 将 Spring 工作负载扩展到零的两种方法,但其中涉及到不小的权衡。如果有另一种方法可以在减少限制的情况下提高 Spring Boot 运行时特性,那会怎样呢?

        您可能听说过 Project Leyden,这是一个新的 OpenJDK 项目,旨在改善 Java 程序的启动时间、达到峰值性能的时间和占用空间。

        Project Leyden 最近引入了 "premain "优化(基本上是类数据共享 + AOT 的类固醇),有趣的是,Java Platform 团队发现了 Spring Ahead-Of-Time 优化的巨大协同作用,Spring Ahead-Of-Time 优化最初是为了支持 GraalVM 原生镜像而创建的,但已经能够将 JVM 的启动时间缩短 15%。

        虽然 "premain "优化是高度实验性的(目前它只是 GitHub 上 Leyden 代码库的一个实验性分支),但 Spring 团队最近通过结合 JVM 上的 Spring AOT 和项目 Leyden 中的这些优化,已经测得 Spring Petclinic 示例应用程序的启动时间缩短了 2 到 4 倍,预热速度也加快了,而且几乎没有任何取舍。

        与 GraalVM 和 CRaC 不同的是,这些优化措施目前还无法实现零扩展,因为它们无法让应用程序在生产中以几十毫秒的速度启动。但是,如果我们能在几乎不受任何限制的情况下显著改善 JVM 的启动和预热时间,那么它就有可能成为主流。

结论

        Spring Boot 3.2的发布,特别强调了现代Java开发中并发处理和安全性的重要性。它通过引入虚拟线程和CRaC等先进特性,使得企业级应用开发更加高效、可靠。这些特性的引入,不仅让Spring Boot在Java开发框架中继续保持领先地位,也极大地推动了Java生态系统的进步。随着开发者社区的探索和采纳这些新特性,进一步增强了其在云原生和微服务架构中的适应性和应用性。

        Spring Boot 3.2不仅仅是一次技术更新,它也是Spring生态系统对现代软件开发挑战的回应,特别是在微服务、云计算和DevOps文化日益盛行的背景下。这些新特性的推出,旨在帮助开发者和企业更好地应对高并发处理需求,提高系统的可伸缩性和可靠性,同时还能在保证安全的前提下提升开发和部署的灵活性。

        总的来说,Spring Boot 3.2的发布为Java开发者社区带来了一股新的生机。它的新特性不仅加强了Spring Boot在应用开发中的核心地位,也为企业提供了一种更强大、更现代的开发工具,以适应不断变化的技术需求和市场动向。

你可能感兴趣的:(springboot,后端技术栈,Java,spring,boot,java,数据库)