咨询下各位大佬,为什么 tomcat 的默认的最大的线程数是 200 ,但是在项目里面( IO 密集型)设置的最大线程数是 2 * CPU 核心数?
1
themostlazyman 2023-12-08 13:56:09 +08:00
Tomcat 多个线程为了提高并发(IO 密集); 2 * CPU 核心数一般是处理器支持一个核虚拟两个核的 CPU 的设置(计算密集或者多进程应用)。
|
2
huang119412 2023-12-08 14:39:15 +08:00
IO 密集型线程数设为 2 * CPU ,此时的 IO 是 NIO , 如果是 OIO 则线程数是 2 * CPU 不合理,Tomcat 一般需要配合关系型数据库使用,Web 项目的瓶颈都是在数据库,而 JDBC (关系型数据库)并不支持异步,异步也没什么意义,所以 Tomcat 的线程数设置的看起来非常多。但是线程的切换时间和 IO 的阻塞时间比基本上可以忽略不记。
|
3
VB1 OP @themostlazyman
@huang119412 感谢二位的回答,但是一个 springboot 里面,内置 tomcat ,在一台机器上(假设 CPU8 核)启动 springboot 项目后,所有的线程共享这台机器的 CPU ,但是为啥 tomcat 的线程数(最大 200)和项目中线程池的线程数(最大 16)相差如此之大。也就是说为什么 tomcat 可以不受这个 2 * CPU 核心数这个限制? |
4
Goooooos 2023-12-08 15:18:56 +08:00
每个请求到在线程池的一个线程处理,大部分请求都由于外部 IO 请求而阻塞,导致该请求所在的线程阻塞
如果同一秒内所有请求都阻塞在 IO 上(如查询 Mysql ),那么此时 CPU 就变得空闲了 加大线程池最大线程数量,可以在同 1 秒内处理更多请求,更好利用 CPU 但线程数量也不能无限大,频繁的上下文切换也是很消耗 CPU 的 升级 JDK21 后可以尝试虚拟线程,这种场景能更好的提高 CPU 利用率 |
5
yty2012g 2023-12-08 15:57:02 +08:00
后面的设置不太合理,如果是 IO 密集型,很容易出现线程池内线程不够用的情况
|
6
anonydmer 2023-12-08 16:10:43 +08:00 1
楼主混淆了两个概念,servlet 容器的线程池和应用业务的线程池。tomcat 配置的 200 个线程是用来处理 servlet 请求的,就是说,有请求到来时候,tomcat 总共用多少个线程来处理请求的业务逻辑操作(不是请求本身的 io ),这个逻辑操作对应的就是你 spring mvc 中某个 controller 的一个 action 方法。 在这些业务逻辑操作中,如果你还需要做多线程操作,就需要你自己管理一个线程池,就是你说的后面这个线程池,因为在业务中一般都是做 io 操作,io 操作不需要很多的线程数量就够了。
|
7
anonydmer 2023-12-08 16:22:32 +08:00
在这种模式下,tomcat 的并发性能其实是受到最大线程数量限制的。太多的线程会对 CPU 造成频繁的上下文切换。 如果系统是 IO 密集型的,针对这个问题先前一种可行的方式是用事件驱动的框架,例如 Spring WebFlux; 但是现在 Java 21 已经支持了虚拟线程,我们可以在不改变编程模型的基础上达到和 SpringWebFlux 类型的性能,目前 SpringBoot 已经支持虚拟现场了,楼主可以测试一下让 tomcat 用虚拟线程,在 IO 场景下,性能会好很多。
|
8
wysnxzm 2023-12-08 16:27:43 +08:00
virtual thread 对这类问题是降维打击
|