对于 QPS,RT 这些名词想必大家都不生疏,然而说到如何晋升他们却束手无策。明天咱们就来钻研一下吧
目录
名称解释
QPS 与线程数的关系
最佳线程数
案例
优化方向
QPS 与 RT 的关系
总结
名词解释
RT(Response Time): 1 个申请所实现的工夫
QPS(Query Per Second): 1 秒钟内所实现的申请数量
QPS 与线程数的关系
对于单线程而言,QPS = 1000ms/RT
比方一个零碎只有一个线程,响应工夫为 50ms,那么它的 qps 就是 1000/50=20
如果它有两个线程,那么它的 qps 为:20*2=40
这里假如不受 cpu、io、内存等其余影响
实践上服务器可能反对的线程数越多,那么 qps 就会越高,qps 与线程数成正比例关系。
当然,服务器的资源是无限的,在理论压测过程中,开始时 QPS 将随着线程数的减少而减少,当线程数达到肯定数量,达到 cpu 瓶颈时,qps 放弃不变,随着持续压测,qps 还会稍微降落,并且响应工夫变长。
起因其实很简略,在 cpu 资源短缺时,线程有足够的 cpu 执行工夫用于运行程序,当线程数达到肯定数量,同时 cpu 资源耗尽时,线程开始争抢 cpu,频繁产生线程上下文切换(该过程非常耗时),线程之间相互期待,响应工夫天然减少。
最佳线程数
通过 QPS 与线程数的关系,能够很容易的就能得出一个概念。
最佳线程数:刚好耗费完服务器资源的临界线程数。
公式:最佳线程数 = ((线程等待时间 + 线程 cpu 工夫)/ 线程 cpu 工夫) * cpu 数量
等价于:最佳线程数 = (线程等待时间 / 线程 cpu 工夫 + 1) * cpu 数量
网上是第一种,等价的公式是我换算的,因为能解释出具体的意义
当然,如果你晓得第一种公式的具体意义,还请通知我
公式阐明
假如在单线程状况下,线程等待时间为 100ms,线程 cpu 工夫为 20ms,在线程期待的 100ms,cpu 是处于闲暇状态,那么咱们便能够把这 100ms 交给其余的线程应用,一共能够给多少个线程应用呢,每个线程须要 cpu20ms,那么就是:100/20 = 5, 再加上本人这个线程就是 6,所以在这一个时间段内 cpu 最大能够摆布的线程数为 6,如果服务器有 2 个 cpu,那么就是 6 *2 = 12。
套用公式:(10/2 + 1)*2 = 12
当然,在理论执行中,必定不是他 20ms 我 20ms 这样的,而是 cpu 为每个线程调配工夫片交替执行
个性
在达到最佳线程数时,线程数量持续减少,但 qps 不变,而响应工夫变长,持续减少线程数,qps 开始降落。
如何失去最佳线程数
1、通过压测的形式,迟缓递增线程数,察看压测状况,依据个性会很容易获得最佳线程数
2、通过公式间接进行计算,这个形式有点难,因为咱们难以晓得零碎的线程 cpu 工夫与线程等待时间
3、依据第一种形式的改良,进行一次压测,察看 cpu 状况,而后将线程数 *(cpu 期望值 / 以后 cpu 值),就会失去一个大略值,而后略作调整即可失去最佳线程数。
案例
为了更好的意识以上实践,并探讨如何晋升 QPS,咱们通过 springboot 构建一个测试案例
定义一个用于模仿 cpu 执行的办法
public long runCpu(int count){long start = System.currentTimeMillis();
// 用几个参数让 cpu 运行
int a = 0;
double b = 0;
long c = 0;
for (int i = 0; i < count; i++) {for (int j = 0; j < 100; j++){
a++;b++;c++;
a=a*2;b=b/2;
a=a/2;b=b*2;
c=c*2;c=c/2;
a--;b--;c--;
}
a++;b++;c++;
}
System.out.println(a);
// 返回运行工夫
return System.currentTimeMillis() - start;}
count 参数使得该办法的运行工夫存在可变性
定义压测接口
/**
* @param count 循环次数,用于模仿 cpu 运行工夫
* @param sleep io 工夫 毫秒
*/
@GetMapping("/benchmark")
public String qps(int count, long sleep) throws InterruptedException {long start = System.currentTimeMillis();
// cpu 运行工夫
long cpuTime = runCpu(count);
long ioStart = System.currentTimeMillis();
// 模仿 io 阻塞
Thread.sleep(sleep);
long ioTime = System.currentTimeMillis() - ioStart;
long total = System.currentTimeMillis() - start;
return "total:"+ total + "cpu-time:" + cpuTime + "io-time:" + ioTime;
}
为了不便测试,我将它做成了镜像,应用 docker 运行
这是我的 docker-compose 文件,给了 2 个 cpu
version: '3.5'
services:
qps-test:
image: qps-test:1.0.0
container_name: qps-test
ports:
- 8080:8080
resources:
limits:
cpus: '2.00'
第一次测试,将 count 调为 100000(这里相当于我机器的 cpu-time 为 10~20ms),io time 为 80ms
http://192.168.65.206:8080/qp…
得出后果如下
RT | qps | cpu | 最佳线程数 |
---|---|---|---|
103 | 125 | 190% | 13 |
单线程的 QPS: 1000/103 = 9.7
可能会有小伙伴不知道怎么调出这个后果的,这里我简略阐明下
首先咱们须要晓得,服务器的瓶颈在 cpu 上,因为我这个案例不可能存在内存瓶颈,所以咱们须要将 cpu 压测到 190% 左后(临界 cpu 的瓶颈),如果压到了 200%,阐明此时线程数很可能曾经超了,cpu 资源已耗尽,就须要升高线程数,如果没到 190%,就持续减少压测线程,直到恒定在 190% 左右。
压测工具我用的是 jmeter
有了这个基准数据,当初就要尝试进行晋升 qps
优化方向
依据公式:QPS = (1000/RT) * 线程数
因为 cpu 资源曾经将要耗尽,那么咱们就只能尝试升高响应工夫
而响应工夫分为两个局部:cpu 工夫和线程等待时间,所以咱们从这两个方面动手。
升高 IO 等待时间
咱们尝试将 io 理论从 80ms 降为 40ms
http://192.168.65.206:8080/qp…
进行压测后果如下:
RT | qps | cpu | 最佳线程数 |
---|---|---|---|
65 | 123 | 190% | 8 |
单线程 QPS: 1000/65 = 15.4
咱们发现响应工夫尽管从原来的 103 变为了 65,但 qps 却简直未变,而最佳线程数从 13 变为了 8
得出结论:升高 IO 工夫并不能晋升 QPS,为什么?
咱们依据 CPU 资源恒定准则:CPU 资源 = 线程的 cpu 工夫 线程总数 单线程的 qps
所以得出式子:基准数据的 cpu 每秒的解决工夫 = 升高 IO 等待时间的 cpu 每秒的解决工夫
23ms 13 9.7 = 25ms x 15.4 解出 x = 7.53
其中 25ms 为 RT(65) – IO(40) 15.4 为 1000/65
线程数 | 单线程 QPS | RT | CPU 解决工夫 | QPS |
---|---|---|---|---|
13 | 9.7 | 103 | 23ms 13 9.7 | 125 |
x ≈ 8 | 15.4 | 65 | 25ms x 15.4 | 123 |
升高 CPU 执行工夫
咱们将 cpu 运行工夫削减个别,count 值 100000 -> 50000
http://192.168.65.206:8080/qp…
进行压测后果如下:
RT | qps | cpu | 最佳线程数 |
---|---|---|---|
101 | 244 | 190% | 25 |
单线程 qps: 1000/101 = 9.9
响应工夫简直未产生扭转,但 QPS 翻了一倍,最佳线程数也翻了一倍
得出结论:升高 cpu 工夫能显著晋升 QPS
同样依据 CPU 资源恒定准则失去:
23ms 13 9.7 = 21ms x 9.9
x ≈ 14
因为未知起因,这里翻车了,按理说 cpu 工夫该当为 10ms 左右,因为 count 值减半了。
如果 cpu 工夫为 10ms~15ms, 那么 x 就靠近 25,合乎压测状况了。这里猜想是因为 io 工夫有误,导致 RT 变长。
小结
count | sleep | RT | qps | cpu | 最佳线程数 |
---|---|---|---|---|---|
100000 | 80ms | 103 | 125 | 190% | 13 |
100000 | 40ms | 65 | 123 | 190% | 8 |
50000 | 80ms | 101 | 244 | 190% | 25 |
QPS 与 RT 的关系
如果说单纯的依据公式:QPS = 1000/RT,QPS 与 RT 的关系如下
但通过案例咱们的得悉,在理论状况下,QPS 与 RT 的关系并非如此,RT 中的存在两种工夫对 QPS 有所影响。
CPU 执行工夫缩小,QPS 显著晋升。
IO 等待时间缩小,QPS 晋升不显著或者无晋升。
总结
通过以上内容分析,如果想要晋升 RT
1、缩小 IO 的响应工夫
2、缩小 CPU 的执行工夫
如果想要晋升 QPS
1、缩小 CPU 的执行工夫
2、减少 CPU 数量
提醒:如果在压测过程中,cpu 还未达到瓶颈,QPS 就曾经达到了峰值,那么则阐明存在其余的瓶颈,如内存
参考资料
https://www.docin.com/p-73662763.html?docfrom=rrela
追更,想要理解更多精彩内容,欢送关注公众号:程序员阿紫
集体博客空间:https://zijiancode.cn
如果我的文章对你有所帮忙,还请帮忙 点赞、转发 一下,你的反对就是我更新的能源,非常感谢!