如何使用wrk压测接口

1 阅读3分钟

安装

brew install wrk

压测参数

pzj@pzjmac ~ % wrk
Usage: wrk <options> <url>                            
  Options:                                            
    -c, --connections <N>  Connections to keep open   
    -d, --duration    <T>  Duration of test           
    -t, --threads     <N>  Number of threads to use   
                                                      
    -s, --script      <S>  Load Lua script file       
    -H, --header      <H>  Add header to request      
        --latency          Print latency statistics   
        --timeout     <T>  Socket/request timeout     
    -v, --version          Print version details      
                                                      
  Numeric arguments may include a SI unit (1k, 1M, 1G)
  Time arguments may include a time unit (2s, 2m, 2h)

-c: 连接数

-d: 压测时长

-t: 压测线程数

-s: lua 脚本路径

-h: 请求头

参考示例

wrk -c100 -d10s -t10 https://blog-api.golangblog.com/config/home

含义:

100 个连接, 10 个线程blog-api.golangblog.com/config/home 这个接口压测 10s

结果分析

Running 10s test @ https://blog-api.golangblog.com/config/home
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   113.26ms  182.88ms   1.66s    90.13%
    Req/Sec   184.11    122.34   430.00     54.91%
  16657 requests in 10.07s, 17.72MB read
  Non-2xx or 3xx responses: 5501
Requests/sec:   1654.68
Transfer/sec:      1.76MB

Latency: 平均响应时长

Req/Sec: 每个线程的QPS

Avg: 平均值

Stdev: 标准差

Max: 最大值

+/- Stdev: 有多少比例的请求,落在「平均值 ± 1 个标准差」这个区间内

Requests/sec: 压测出来的全局QPS

Transfer/sec: 每秒平均占用带宽大小

如何评判一个接口的好坏

QPS(每秒最多能处理多少个请求,往往反映该接口的吞吐量) 并不是评判一个接口好坏的唯一标准

主要通过以下几种方式

1. 错误率

结果中包含 Non-2xx or 3xx responses: 5501,代表非 2xx-3xx 之间的错误,那么就是 4xx-5xx(客户端或者服务端错误)

5501/16657 = 33%, 错误率约 33%

评判标准

  • 目标:≈ 0%
  • 可接受:< 0.1%
  • 危险:> 1%
  • 不可用:> 5%

2. 尾延迟

尾延迟通常用这些指标表示:

  • P95:95% 请求比这个快
  • P99:99% 请求比这个快
  • P999:99.9% 请求比这个快

举个例子

P50  = 50ms
P95  = 200ms
P99  = 1.5s

含义:

  • 一半请求很快(50ms)
  • 大部分还行(200ms)
  • 但有 1% 请求慢到 1.5秒

这个 1.5s 就是典型的尾延迟

wrk 带上 --latency 可以获取到请求时间的分布

pzj@pzjmac ~ % wrk -c100 -d10s -t10 --latency https://blog-api.golangblog.com/config/home 
Running 10s test @ https://blog-api.golangblog.com/config/home
  10 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   246.60ms  318.68ms   1.98s    87.53%
    Req/Sec    73.05     97.49   444.00     87.07%
  Latency Distribution
     50%  113.02ms
     75%  311.00ms
     90%  643.50ms
     99%    1.51s 
  6286 requests in 10.07s, 6.06MB read
  Non-2xx or 3xx responses: 3286
Requests/sec:    624.11
Transfer/sec:    615.81KB

业界通用判断标准

指标优秀可接受
P95< 100ms< 300ms> 500ms
P99< 200ms< 1s> 1s

3. 稳定性

(标准差/平均值)

CV结论
< 0.3稳定
0.3~0.5有波动
> 0.5不稳定
> 1过载

4. 平均延迟

只能作为参考

延迟(Avg / P50)评价说明
< 10ms极优内存级 / 本地缓存
10 ~ 50ms优秀高频接口理想状态
50 ~ 100ms良好常规业务推荐范围
100 ~ 200ms一般用户开始能感知
200 ~ 500ms较差明显变慢
500ms ~ 1s很差用户明显卡顿
> 1s不可接受必须优化

业界通用指标

✔ 错误率 ≈ 0
✔ P99 在可控范围(200ms以下)
✔ CV < 0.3(稳定)
✔ QPS 在目标负载下稳定

保证上述的同时,选择合适的线程数(与电脑的 CPU 数量有关),渐进式增大 c,找到该接口的最大拐点,测出稳定状态下的最大请求数量

在不断调整下

pzj@pzjmac ~ % wrk -c18 -d10s -t10 --latency https://blog-api.golangblog.com/config/home 
Running 10s test @ https://blog-api.golangblog.com/config/home
  10 threads and 18 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    76.36ms   13.38ms 168.20ms   81.25%
    Req/Sec    12.84      4.84    20.00     65.91%
  Latency Distribution
     50%   71.89ms
     75%   78.84ms
     90%   96.56ms
     99%  121.26ms
  1307 requests in 10.09s, 2.11MB read
Requests/sec:    129.56
Transfer/sec:    213.71KB

得到博客在稳定状态下最大 QPS 为 129,使用裸 ip 的 QPS 大约在 220 左右,主要原因是TLS / HTTPS 的开销

总结

性能测试的目标不是跑高数据,而是找到系统在“稳定 + 可用”前提下的真实上限。