Spring Boot 3.2 于 2023 年 11 月大张旗鼓地发布,标志着 Java 开发领域的一个关键时刻。这一突破性的版本引入了一系列革命性的功能,包括:

  • 虚拟线程:利用 Project Loom 的虚拟线程释放可扩展性,从而减少资源消耗并增强并发性。
  • Native Image支持:通过Native Image编译制作速度极快的应用程序,减少启动时间并优化资源利用率。
  • JVM 检查点:利用 CRaC 项目的 JVM 检查点机制实现应用程序的快速重启,无需冗长的重新初始化。
  • RestClient:采用新的 RestClient 接口的功能方法,简化 HTTP 交互并简化代码。
  • Spring for Apache Pulsar:利用 Apache Pulsar 的强大功能实现强大的消息传递功能,无缝集成到您的 Spring Boot 应用程序中。

其中,虚拟线程是最近 Java 版本中引入的最具变革性的特性之一。正如官方文件所述:虚拟线程是轻量级线程,可减少编写、维护和调试高吞吐量并发应用程序的工作量。线程是可以调度的最小处理单元。它与其他此类单位同时运行,并且在很大程度上独立于其他此类单元运行。它是 java.lang.Thread 的一个实例。有两种线程:平台线程和虚拟线程。平台线程是作为操作系统 (OS) 线程的瘦包装器实现的。平台线程在其底层操作系统线程上运行 Java 代码,平台线程在平台线程的整个生命周期内捕获其操作系统线程。因此,可用平台线程数限制为操作系统线程数。与平台线程一样,虚拟线程也是 java.lang.Thread 的实例。但是,虚拟线程不绑定到特定的操作系统线程。虚拟线程仍在操作系统线程上运行代码。但是,当在虚拟线程中运行的代码调用阻塞 I/O 操作时,Java 运行时会挂起虚拟线程,直到它可以恢复为止。与挂起的虚拟线程关联的操作系统线程现在可以自由地对其他虚拟线程执行操作。虚拟线程适用于运行大部分时间被阻塞的任务,通常等待 I/O 操作完成。但是,它们不适用于长时间运行的 CPU 密集型操作。

虽然人们普遍认为虚拟线程在 I/O 密集型方案中表现出色,但它们在 CPU 密集型任务中的性能仍然是一个问号。本系列文章深入探讨了虚拟线程在各种用例中的潜在优势,从基本的“hello world”到静态文件服务(I/O 密集型)、QR 码生成(CPU 密集型)和多部分/表单数据处理(混合工作负载)等实际应用。

在本系列的开头文章中,我们已经了解了虚拟线程与物理线程相比在最简单(且不切实际)的 hello world 情况下的性能。物理线程和虚拟线程之间几乎没有任何性能或资源使用差异。在本文中,我们将更加“实用”,并针对静态文件服务器情况进行比较。这绝对是一个常见且“真实世界”的案例。让我们看看这次我们发现了什么。

如果大家正在做Spring Boot 2.3升级Spring 3.2,这里顺手给大家推荐Spring Boot 2.x 到 3.2 的升级指南

测试环境

所有测试均在配备 16G RAM、8 个物理内核和 4 个效率内核的 MacBook Pro M2 上执行。测试工具是 Bombardier,它是更快的 HTTP 负载测试器之一(用 Go 编写)。

软件版本为:

  • Java v21.0.1
  • Spring Boot 3.2.1

程序配置

除了主 Java 类之外,不需要编写任何 Java 文件,静态文件服务器只能通过配置就能发挥作用。

application.properties文件如下:

server.port=3000
spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=file:/Users/mayankc/Work/source/perfComparisons/static/

使用虚拟线程时,我们将通过添加以下行来启用它们:

spring.threads.virtual.enabled=true

pom.xml内容:

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
<relativePath/>
</parent>
<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>21</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

测试数据

大小完全相同但数据不同的 100K 文件被放置在静态资源目录中。每个文件大小正好是 102400 字节。

文件的命名范围为 1 到 100000。

使用 Bombardier 的修改版本,为每次运行生成随机请求 URL: http://localhost:3000/static/<file-name>

应用场景

为了确保结果一致,每个测试在开始数据收集之前都会经历 5K 请求预热阶段。

然后,在不同范围的并发连接级别(50、100 和 300)中仔细记录测量结果,每个级别都承受 500 万个请求工作负载。

结果评估

除了简单地跟踪原始速度之外,我们还将采用详细的指标框架来捕获延迟分布(最小值、百分位数、最大值)和吞吐量(每秒请求数)。

CPU 和内存的资源使用情况监控将补充此分析,从而提供不同工作负载下系统性能的全面了解。

测试结果

结果以图表形式呈现如下:

总结

对静态文件服务的分析表明,物理线程在性能和资源效率方面略胜一筹(与我们的预期相反)。

不过,这种受 I/O 限制的场景可能并不是充分发挥虚拟线程潜力的理想场所。涉及数据库交互的任务可能会显示出更多令人信服的优势。也许负载不足以让虚拟线程发挥出最大的作用。为了找出答案,我们将在接下来的文章中介绍 URL短链(数据库驱动)、二维码生成(CPU受限)和混合工作负载场景(如表单数据处理),旨在揭示虚拟线程真正出类拔萃的案例。

欢迎关注我的公众号:程序猿DD。第一时间了解前沿行业消息、分享深度技术干货、获取优质学习资源

用Spring Boot 3.2虚拟线程搭建静态文件服务器有多快?的更多相关文章

  1. spring boot / cloud (四) 自定义线程池以及异步处理@Async

    spring boot / cloud (四) 自定义线程池以及异步处理@Async 前言 什么是线程池? 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务.线 ...

  2. Spring Boot 项目学习 (一) 项目搭建

    0 引言 本文主要记录借用Idea 开发环境下,搭建 Spring Boot 项目框架的过程. 1 系列文档目录 Spring Boot 项目学习 (一) 项目搭建 Spring Boot 项目学习 ...

  3. CentOS 6(64-bit) + Nginx搭建静态文件服务器

    Nginx搭建静态文件服务器 使用命令打开Nginx配置文件: sudo vim /etc/nginx/conf.d/default.conf 将配置改为: server { ...... ..... ...

  4. Ubuntu 14.04TLS Nginx搭建静态文件服务器

    Nginx搭建静态文件服务器 [官方教程]https://www.nginx.com/resources/admin-guide/serving-static-content/ 打开Nginx的配置文 ...

  5. 【ELK】5.spring boot日志集成ELK,搭建日志系统

    阅读前必看: ELK在docker下搭建步骤 spring boot集成es,CRUD操作完整版 ============================================== 本章集成 ...

  6. spring boot+mybatis+quartz项目的搭建完整版

    1. 利用spring boot提供的工具(http://start.spring.io/)自动生成一个标准的spring boot项目架构 2. 因为这里我们是搭建spring boot+mybat ...

  7. Spring Boot学习笔记---Spring Boot 基础及使用idea搭建项目

    最近一段时间一直在学习Spring Boot,刚进的一家公司也正好有用到这个技术.虽然一直在学习,但是还没有好好的总结,今天周末先简单总结一下基础知识,等有时间再慢慢学习总结吧. Spring Boo ...

  8. Spring Boot微服务框架的搭建

    (1)spring boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发 ...

  9. spring boot:使用多个线程池实现实现任务的线程池隔离(spring boot 2.3.2)

    一,为什么要使用多个线程池? 使用多个线程池,把相同的任务放到同一个线程池中,可以起到隔离的作用,避免有线程出错时影响到其他线程池,例如只有一个线程池时,有两种任务,下单,处理图片,如果线程池被处理图 ...

  10. spring boot:使用async异步线程池发送注册邮件(spring boot 2.3.1)

    一,为什么要使用async异步线程池? 1,在生产环境中,有一些需要延时处理的业务场景: 例如:发送电子邮件, 给手机发短信验证码 大数据量的查询统计 远程抓取数据等 这些场景占用时间较长,而用户又没 ...

随机推荐

  1. Trie字典

    Trie树,又叫字典树,前缀树(Prefix Tree),单词查找树,是一种多叉树的结构. {"a","apple","appeal",&q ...

  2. JUC并发编程(1)—CompletableFuture详解

    @ 目录 CompletableFuture介绍 1.创建异步任务 2.CompletableFuture API ①. 获得结果和触发计算(get.getNow.join.complete) ②. ...

  3. umich cv-2-1

    UMICH CV Linear Classifiers 对于使用线性分类器来进行图片分类,我们可以给出这样的参数化方法: 而对于这样一个式子,我们怎么去理解呢? 首先从代数的角度,这个f(x,W)就是 ...

  4. .NET 数据库大数据 方案(插入、更新、删除、查询 、插入或更新)

    1.功能介绍 (需要版本5.0.45) 海量数据操作ORM性能瓶颈在实体转换上面,并且不能使用常规的Sql去实现 当列越多转换越慢,SqlSugar将转换性能做到极致,并且采用数据库最佳API 操作数 ...

  5. code2uml使用教程

    通常的开发顺序是 先设计uml然后进行code编程. 但是很多时候我们是先看到code源码,却不知道uml关系如何. 特别是写论文的时候也是很需要的. 这个code2uml,就是辛苦搜寻到的结果,可以 ...

  6. PyCharm配置autopep8(自动格式化Python代码)

    PyCharm配置autopep8(自动格式化Python代码)   1. 关于PEP 8 PEP 8,Style Guide for Python Code,是Python官方推出编码约定,主要是为 ...

  7. ProcessingJS

    ProcessingJS 图形 rect(x, y, w, h)(在新窗口中打开) ellipse(x, y, w, h) triangle(x1, y1, x2, y2, x3, y3) line( ...

  8. EMC ndmp NAS

    NAS 是带存储系统的专用高性能文件服务器.它可提供文件级数据访问和共享. NAS 使用网络和文件共享协议,包括用于数据传输的 TCP/IP 以及用于远程文件服务的 CIFS 和 NFS. 最简单的备 ...

  9. Anaconda虚拟环境配置Python库与Spyder编译器

      本文介绍在Anaconda中,为Python的虚拟环境安装第三方库与Spyder等配套软件的方法.   在文章创建Anaconda虚拟Python环境的方法中,我们介绍了在Anaconda环境下, ...

  10. sql删除进程

    使用一下语句杀掉进程 USE master go DECLARE @dbname VARCHAR(200) SET @dbname = 'xxxx' --要关闭进程的数据库名 DECLARE @sql ...