Spring Boot 3.2四个新特点提升运行性能
随着 Spring Framework 6.1 和 Spring Boot 3.2 普遍可用性的临近,我们想分享一下 Spring 团队为让开发人员优化其应用程序的运行时效率而做出的几项努力的概述。
我们将介绍以下技术和用例:
- Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈
- 使用 Spring 和 GraalVM Native Image 优化容器部署
- JVM 检查点恢复:使用 Spring 和 Project CRaC 扩展到零
- 通过 Spring AOT 和 Leyden 项目一睹 OpenJDK 的未来
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,并使用最新的库和驱动程序版本来评估虚拟线程。
2、使用 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 原生镜像所要求的权衡的项目来说,如何将其扩展为零呢?
3、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 支持的发展,其中一些限制可能会被取消。
4、通过 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 的启动和预热时间,那么它就有可能成为主流。
来自:https://www.jdon.com/69141.html
相关文章:
Spring Boot 3.2四个新特点提升运行性能
随着 Spring Framework 6.1 和 Spring Boot 3.2 普遍可用性的临近,我们想分享一下 Spring 团队为让开发人员优化其应用程序的运行时效率而做出的几项努力的概述。 我们将介绍以下技术和用例: Spring MVC 将使用 基于JDK 21 虚拟线程 Web 堆栈使用 Spri…...
一阶系统阶跃响应实现规划方波目标值
一阶系统单位阶跃响应 一阶系统传递函数,实质是一阶惯性环节,T为一阶系统时间常数。 输入信号为单位阶跃函数,数学表达式 单位阶跃函数拉氏变换 输出一阶系统单位阶跃响应 拉普拉斯反变换 使用前向差分法对一阶系统离散化 将z变换写成差分方…...
项目经理如何去拆分复杂项目?
代码的横向分层,维度是根据复杂度来的,可保证代码便于开发和维护 1、因为强类型的原因,把变动大的分到数据库来解决,这是一种后端分离。 2、因为发布难的原因,所以用稳定的引擎来解决问题,然后用数据库配置…...
python二次开发Solidworks:修改实体尺寸
立方体原始尺寸:100mm100mm100mm 修改后尺寸:10mm100mm100mm import win32com.client as win32 import pythoncomdef bin_width(width):myDimension Part.Parameter("D1草图1")myDimension.SystemValue width def bin_length(length):myDime…...
【C++】:类和对象(中)之类的默认成员函数——构造函数and析构函数
1.类的6个默认成员函数 如果一个类中什么成员都没有,简称为空类 空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数 默认成员函数:用户没有显式实现,编译器会生成…...
sqlserver系统存储过程添加用户学习
sqlserver有一个系统存储过程sp_adduser;从名字看是添加用户的;操作一下, 从错误提示看还需要先添加一个登录名,再执行一个系统过程sp_addlogin看一下, 执行完之后看一下,安全性-登录名下面有了rabbit&…...
Monocle 3 | 太牛了!单细胞必学R包!~(一)(预处理与降维聚类)
1写在前面 忙碌的一周结束了,终于迎来周末了。🫠 这周的手术真的是做到崩溃,2天的手术都过点了。🫠 真的希望有时间静下来思考一下。🫠 最近的教程可能会陆续写一下Monocle 3,炙手可热啊,欢迎大…...
基于VCO的OTA稳定性分析的零交叉时差模型研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
大数据Hadoop之——部署hadoop+hive+Mysql环境(window11)
一、安装JDK8 【温馨提示】对应后面安装的hadoop和hive版本,这里使用jdk8,这里不要用其他jdk了,可能会出现一些其他问题。 1)JDK下载地址 Java Downloads | Oracle 按正常下载是需要先登录的,这里提供一个不用登录下载…...
app爬虫中的Airtest元素存在或等待
app爬虫中的Airtest元素存在或等待 一. poco等待 等待无错误 等待元素10秒。如果它没有出现,则不会引发任何错误。 poco(xxx).wait(timeout10)您还可以在.wait()之后执行一些操作,如click或long_click poco(xxx).wait(timeout10).click() poco(xxx).…...
Flink学习之旅:(三)Flink源算子(数据源)
1.Flink数据源 Flink可以从各种数据源获取数据,然后构建DataStream 进行处理转换。source就是整个数据处理程序的输入端。 数据集合数据文件Socket数据kafka数据自定义Source 2.案例 2.1.从集合中获取数据 创建 FlinkSource_List 类,再创建个 Student 类…...
SQL INSERT INTO 语句(在表中插入)
SQL INSERT INTO 语句 INSERT INTO 语句用于向表中插入新的数据行。 SQL INSERT INTO 语法 INSERT INTO 语句可以用两种形式编写。 第一个表单没有指定要插入数据的列的名称,只提供要插入的值,即可添加一行新的数据: INSERT INTO table_n…...
2023年最佳项目管理软件排行榜揭晓!
根据网络数据调查结果显示,今年有77%的组织将效率列为优先事项,而82%的领导人确认投资于新的项目管理和工作管理方案以提高效能。然而随着对价值的重新关注,选择适合的工程项目管理软件变得比以往任何时候都更加重要。好消息是通过对39个主要…...
华为OD DNA序列(100分)【java】A卷+B卷
华为OD统一考试A卷B卷 新题库说明 你收到的链接上面会标注A卷还是B卷。目前大部分收到的都是B卷。 B卷对应20022部分考题以及新出的题目,A卷对应的是新出的题目。 我将持续更新最新题目 获取更多免费题目可前往夸克网盘下载,请点击以下链接进入ÿ…...
idea2023配置maven
看过【黑马程序员Maven全套教程,maven项目管理从基础到高级,Java项目开发必会管理工具maven】https://www.bilibili.com/video/BV1Ah411S7ZE?p9&vd_sourceedf9d91e5a0a27db51e3d6d4b9400637 配置的,前提要素配置也在这个课程里有啦&…...
Python 文件打包成可执行文件
打包 要将Python脚本打包成可执行文件,常见的做法是使用PyInstaller或cx_Freeze工具。下面是使用PyInstaller的基本步骤: 使用conda安装pyinstaller (建议) conda install -c conda-forge pyinstaller上面的命令从conda-forge通…...
14-bean创建流程5-初始化和循环依赖
文章目录 1.初始化和循环依赖1.1 初始化步骤1.2 循环依赖问题的产生1.3 如何解决循环依赖问题1.4 解决循环依赖二级缓存即可完成,为什么需要三级缓存1.5循环依赖有时报错1.初始化和循环依赖 1.1 初始化步骤 填充属性执行Aware执行BeanPostProcessor的postProcessBeforeInitia…...
drawio模板以及示例
drawio都能做那些事情和模板示例 你可以使用drawio,并使用drawio提供的扩展模板库和大量的形状库,针对很多不同的工业领域创建不同类型的图表。 针对如下的内容中的所有的图,均可以下载源文件并导入到drawio中再次编辑(供学习者…...
YOLOv8改进实战 | 更换主干网络Backbone(四)之轻量化模型MobileNetV3
前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操作,并将它们分别作用于输入的不…...
22-数据结构-内部排序-选择排序
简介:每一趟选择最小或最大的一个,排在前面或后面。主要右简单选择排序和堆排序 一、简单选择排序 1.1简介: 每趟选择最小的,放在前面,一次类推,代码思想:两个循环,外循环是趟数&a…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
大语言模型如何处理长文本?常用文本分割技术详解
为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...
2025盘古石杯决赛【手机取证】
前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
在golang中如何将已安装的依赖降级处理,比如:将 go-ansible/v2@v2.2.0 更换为 go-ansible/@v1.1.7
在 Go 项目中降级 go-ansible 从 v2.2.0 到 v1.1.7 具体步骤: 第一步: 修改 go.mod 文件 // 原 v2 版本声明 require github.com/apenella/go-ansible/v2 v2.2.0 替换为: // 改为 v…...
计算机系统结构复习-名词解释2
1.定向:在某条指令产生计算结果之前,其他指令并不真正立即需要该计算结果,如果能够将该计算结果从其产生的地方直接送到其他指令中需要它的地方,那么就可以避免停顿。 2.多级存储层次:由若干个采用不同实现技术的存储…...
【Qt】控件 QWidget
控件 QWidget 一. 控件概述二. QWidget 的核心属性可用状态:enabled几何:geometrywindows frame 窗口框架的影响 窗口标题:windowTitle窗口图标:windowIconqrc 机制 窗口不透明度:windowOpacity光标:cursor…...
