wrk的隐藏公式

1,476 阅读3分钟

最近使用wrk做服务压测时有一些思考和实验,觉得挺有意思的,在此做个记录。

测试在公司的K8S容器环境中进行。

0. 猜想

猜想一:

由于wrk压测的是http,http是串行的,故在同一个连接中,需要等待一个请求返回后再请求下一个。因而一个连接的QPS取决于平均响应时间。总的请求QPS = 1/平均响应时间 * 连接数。故想负载充分,一定要加大连接。

猜想二:

假设服务只用一个线程处理请求(或运行在一台机器上),且请求的处理是纯CPU计算,则服务能负载的最大QPS就是 1/平均响应时间,此时CPU跑满。

那么若服务运行在多核机器上,且使用多线程,且请求的处理是纯CPU计算,则服务最大能负载的QPS就是 1/平均响应时间 * 核数。

然而实际上处理请求不可能是纯CPU计算,大部分其实是网络等待时间。此时等待的线程会让出CPU时间。所以服务最大能负载的QPS会大于 1/平均响应时间 * 核数。

总结:

1/平均响应时间 * 核数 < QPS <= 1/平均响应时间 * 连接数

转化一下就是:

核数 < QPS * 平均响应时间 <= 连接数

下面我们就来做实验验证这个猜想。被测服务是一个Java的SpringBoot服务。

0X1. 压测开始

wrk使用 2 线程,8连接压单实例的 s1,4k个商品。服务有4核。

wrk -t2 -c8 -d1000s -T10s --latency -s wrk.txt http://xxx:8080/srch-sort/v1/fine-sort

QPS 120, 平均延时64ms,TP90 80ms,TP99 95ms

平均延时 * QPS 为 7.2, 大于核数4,但刚好小于连接数8,看起来没压到瓶颈。

此时该节点的CPU已打满

wrk使用 4 线程,16连接压单实例的 s1,4k个商品。服务有4核。

QPS 105,平均延时148 ms,TP90 200ms,TP99 220ms,实例CPU打满

平均延时 * QPS 为 15,刚好小于连接数16,看起来没压好。

wrk使用 4 线程,16连接压单实例的 s1。只有2个商品。服务有4核。

QPS 1.8k, 平均延时8ms,TP90 12ms,TP99 27ms,CPU打满

平均延时 * QPS 为 15 s,刚好小于连接数16,看起来没压好。

0X2. 增加连接数

wrk使用 2 线程,32连接压单实例的 s1,4k个商品。服务有4核。

这次服务选择用 106 QPS和 300ms的平均延时来接近32. CPU压满。

所以推论三:wrk会穷尽所有的连接尽力发送,而压测的结果是响应时间和QPS形成动态均衡。QPS不会一直增长,在达到负载顶峰后会下降(抛物线)。我们压测想达到的目标就是找到抛物线的顶点。

wrk使用 2 线程,12连接压单实例的 s1,4k个商品。服务有4核。

这次是QPS 135 和 平均延时88ms,差不多是顶峰了。

0X3. 减少核数至1

wrk使用 2 线程,12连接压单实例的 s1,4k个商品。服务有1核。

这次是QPS 26,平均延时447。

乘积还是12,但性能下降了4倍以上。

0X4. 增加实例数至4

wrk使用 2 线程,12连接压单实例的 s1,4k个商品。服务有1核,4个实例。

结果是QPS 125, 平均延时 95ms。相当于1个实例4核的水平。

0X5. 使用wrk2的-R限制流量

wrk还有个进化版wrk2. (未完待续)