天天用线程池,线程数究竟设置多少才是合理的?

架构之道与术

共 1196字,需浏览 3分钟

 · 2021-08-25

在日常工作中,经常遇到凭感觉、凭经验来设置线程池的线程数,但这背后实际隐藏着深刻的计算机原理。


1. 1 + N + M的线程模型

在讨论线程数之前,先说明一个最典型的服务器程序的线程模型,无论是Java(Tomcat,Netty),还是C++,通常都是这个套路。

1:1个监听线程,监听新来的socket

N:N个IO线程,负责对socket进行读写。N一般等于cpu核数

M:业务逻辑处理线程。


这里所说的线程数,就是指M应该多大合适?


2. CPU密集 vs. IO密集

线程数的设置反映了一个基本的计算机原理:你的应用是cpu密集型 vs. IO密集型?


极端情况,没有任何IO的情况下,每个核1个线程就够了,有多少个核,就有多少个线程。

更进一步,因为没有后端的IO,可以把1 + N + M模型合并成一个线程,这个线程既负责网络入口的IO,也负责业务逻辑处理,最典型的就是Redis。


但实际中,我们的程序往往都有网络IO,比如访问DB,访问Redis,访问Kafka。

假设CPU: IO占比是3:7,那线程数 = cpu核数 * 7/3。也就是:IO越多,CPU会越闲。要想充分利用CPU,就需要开更多的线程。


问题在于:我们如何精确知道CPU: IO的比例是多少?1:9, 3:7, 还是4:6?


3. 如何精确测算CPU: IO比

这个比例是由代码逻辑决定的,没有办法凭感觉去猜测。一个测算方法就是对代码的耗时进行打点,统计代码的执行耗时。看一个请求处理的总时间里面,CPU计算占了多少时间,IO占了多少时间。


但实际场景比这个更复杂,一个复杂的系统肯定不止一个接口,每个接口业务逻辑不一样,CPU:IO比例也不一样。在这种情况下,怎么测算呢?

假设通过代码打点,知道了:

接口1:cpu:io = 1:9

接口2: cpu:io = 3:7

接口3:   cpu:io = 2:8

接口4:   cpu:io = 1:9


最终,整个系统的cpu:io比例是多少呢?所有接口的cpu:io比求平均值?

显然不是。对于一个系统来说,每个接口的调用量并不是一样的,我们可以通过监控系统查看历史调用量的统计数据,得到每个接口的调用量占比,系统的cpu:io比是所有接口的加权平均。即:


整个系统的cpu: io = 接口1的调用量占比 * 接口1的cpu:io比 + 接口2的调用量占比 * 接口2的cpu:io比 + … + 接口N的调用量占比 * 接口N的cpu:io比


最终,知道了这个比例,就能合理的设置线程数了。


浏览 101
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报