文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

SpringBoot3虚拟线程 & 反应式(WebFlux) & 传统Tomcat线程池性能对比

2024-11-30 02:30

关注

1. 简介

从Spring Boot 3.2 支持虚拟线程。要使用虚拟线程,需要在 Java 21 上运行,并将属性 spring.threads.virtual.enabled 设置为 true。

启用虚拟线程后,Tomcat 和 Jetty 将使用虚拟线程处理请求。这意味着处理网络请求的应用程序代码(如控制器中的方法)将在虚拟线程上运行。

启用虚拟线程后,applicationTaskExecutor Bean 将成为配置为使用虚拟线程的 SimpleAsyncTaskExecutor。任何使用应用程序任务执行器的地方,如调用 @Async 方法时的 @EnableAsync、Spring MVC 的异步请求处理和 Spring WebFlux 的阻塞执行支持,现在都将使用虚拟线程。

接下来将分别通过传统阻塞Servlet技术、使用虚拟线程及使用反应式技术WebFlux来分别对比它们的性能。

2. 性能对比

使用虚拟线程 & 传统Servlet都使用下面的接口:

@RestController
@RequestMapping("/task/default")
public class TaskDefaultController {


  @GetMapping("")
  public Object index() throws Exception {
    System.out.printf("before - %s%n", Thread.currentThread()) ;
    TimeUnit.MILLISECONDS.sleep(100) ;
    System.out.printf("after - %s%n", Thread.currentThread()) ;
    return "task - default..." ;
  }
}

先测试下启用虚拟线程执行情况。

配置:

spring:
  threads:
    virtual:
      enabled: true

控制台输出:

before - VirtualThread[#42,tomcat-handler-0]/runnable@ForkJoinPool-1-worker-1
after - VirtualThread[#42,tomcat-handler-0]/runnable@ForkJoinPool-1-worker-1

使用的是虚拟线程。

2.1 传统Tomcat线程池方式

配置线程池,如果不配置使用默认的最大线程200,整体的吞吐量将在2200作用。

server:
  tomcat:
    threads:
      min-spare: 500
      max: 1000

初始启动服务后,内存,CPU占用情况;默认启动后线程个数与上面配置一致。

图片

使用jmeter测试,配置如下:

图片

使用500个线程,循环200次,整体做100000次压测。后续的测试都会基于该配置进行。

图片

吞吐量为:4696

内存,CPU占用情况

图片

2.2 使用虚拟线程

首先开启虚拟线程

spring:
  threads:
    virtual:
      enabled: true

初始启动服务后,内存,CPU占用情况

图片

jmeter测试情况如下:

图片

吞吐量为:4677,与上面的阻塞Servlet基本差不多。但传统Tomcat线程池方式需要更多的线程才能达到这一值。

图片

整个过程内存使用情况,虚拟线程要比传统Tomcat线程池方式占用的多。

JDK 的虚拟线程调度器是一个工作偷取 ForkJoinPool,以先进先出(FIFO)模式运行。调度器的并行性是指可用来调度虚拟线程的平台线程数。默认情况下,它等于可用处理器的数量,但可以通过系统属性 jdk.virtualThreadScheduler.parallelism 进行调整。ForkJoinPool 与普通池不同,普通池用于并行流的实现,并以后进先出模式运行。

调整数量再进行测试,设置JVM参数

-Djdk.virtualThreadScheduler.parallelism=100 -Djdk.virtualThreadScheduler.maxPoolSize=100

设置100个平台线程来调用虚拟线程。

启动服务后,线程,内存使用情况。

图片

jmeter测试结果如下:

图片

与调整前没什么区别,反而是增加了应用的线程数量。

2.3 反应式WebFlux

引入依赖


  org.springframework.boot
  spring-boot-starter-webflux

基于webflux,我们需要重新编写接口测试。

@RestController
@RequestMapping("/task/reactor")
public class ReactorController {


  @GetMapping("")
  public Object index() throws Exception {
    // 与上面2种方式不同,reactor方式则需要使用delayElement方式来模拟耗时任务
    return Mono.just("task - reactor...").delayElement(Duration.ofMillis(100)) ;
  }
}

初始启动服务后,内存,CPU占用情况。

图片

jmeter测试情况如下:

图片

吞吐量为:4659,与上面的测试结果基本一致。

图片

内存使用情况要比前面几种方式占用都少。同时通过jmeter测试结果也能发现,MAX请求的最大响应时间webflux是最小的,Std.Dev:所有请求响应时间的标准差也是最小的(该值越小,平均值越可靠)。

根据测试结果,虚拟线程与webflux谁更胜一筹还不够清晰,接下来我们结合数据库操作进行测试。

3. 基于数据库测试

数据库数据准备了600w的数据。

图片

3.1 传统Tomcat线程池方式

基于JPA进行数据库的操作

@Entity
@Table(name = "t_user")
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Integer uid ;
  private String name ;
}

Repository接口

public interface UserRepository extends JpaRepository {
}

Controller测试接口

@RestController
@RequestMapping("/users")
public class UserController {


  @Resource
  private UserRepository ur ;
  
  @GetMapping("/count")
  public User count() {
    return ur.findById(5800000).orElse(null) ;
  }
  
}

测试结果:

图片

3.2 使用虚拟线程

记得开启虚拟线程,测试结果如下:

图片

3.3 反应式WebFlux

需要引入如下依赖


  org.springframework.boot
  spring-boot-starter-data-r2dbc


  com.github.jasync-sql
  jasync-r2dbc-mysql
  2.1.24

配置

spring:
  r2dbc:
    url: r2dbc:mysql://localhost:3306/batch?serverZnotallow=GMT%2B8&sslMode=DISABLED
    username: root
    password: xxxooo
    pool:
      initialSize: 100
      maxSize: 100
      max-acquire-time: 30s 
      max-idle-time: 30m

实体定义,这里的注解与jpa不一样

@Table("t_user")
public class User {
  
  @Id
  private Integer uid ;
  private String name ;
}

Repository定义

public interface UserR2DBCRepository extends ReactiveCrudRepository {
}

Controller接口

@RestController
@RequestMapping("/r2dbc")
public class UserR2DBCController {


  @Resource
  private UserR2DBCRepository ur ;
  
  @GetMapping("/users")
  public Mono count() {
    return ur.findById(5800000)  ;
  }
  
}

测试结果

图片

根据测试结果来,webflux的整体性能远远高于虚拟线程及传统tomcat线程池的方式。

以上是本篇文章全部内容,希望对你有帮助。

完毕!!!

来源:Spring全家桶实战案例源码内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯