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

目录

  • 前言

  • [Spring Boot 3.2.0系统要求](#Spring Boot 3.2.0系统要求)

  • [Spring Boot 3.2.0 新特性和改进](#Spring Boot 3.2.0 新特性和改进)

  • [Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈](#Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈)

  • [使用 Spring 和 GraalVM 原生镜像优化容器部署](#使用 Spring 和 GraalVM 原生镜像优化容器部署)

  • [JVM 检查点恢复:利用 Spring 和 CRaC 项目实现零扩展](#JVM 检查点恢复:利用 Spring 和 CRaC 项目实现零扩展)

  • [通过 Spring AOT 和 Project Leyden 一窥 OpenJDK 的未来](#通过 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 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在应用开发中的核心地位,也为企业提供了一种更强大、更现代的开发工具,以适应不断变化的技术需求和市场动向。

相关推荐
菜萝卜子7 分钟前
【Redis】redis主从哨兵
数据库·redis·缓存
蒂法就是我12 分钟前
MySQL 的锁,表级锁是哪一层的锁?行锁是哪一层的锁?
数据库·mysql
backRoads16 分钟前
docker部署springboot(eureka server)项目
spring boot·docker·eureka
lozhyf16 分钟前
Eureka搭建
java·spring cloud
幽络源小助理26 分钟前
SpringBoot民宿管理系统开发实现
java·spring boot·springboot·民宿系统
东阳马生架构28 分钟前
Nacos简介—1.Nacos使用简介
java
爱发飙的蜗牛33 分钟前
springboot--web开发请求参数接收注解
java·spring boot·后端
IvanCodes35 分钟前
MySQL 锁机制
数据库·sql·mysql·oracle
青春不流名41 分钟前
docker-compose之graylog
数据库·mongodb
码熔burning1 小时前
【MQ篇】RabbitMQ之工作队列模式!
java·分布式·rabbitmq·mq