wrk(1)- 详细使用

本文涉及的产品
性能测试 PTS,5000VUM额度
简介: wrk(1)- 详细使用

背景


  • 公司对 http 接口都是直接用 wrk 进行压测,简单快捷
  • 刚好有个压测任务分到我
  • 而且中台跟 Lua 也有关系,刚好 wrk 也支持 Lua 脚本,所以学起来,再用起来

 

介绍


  • wrk 是一个类似 ab(apache bench)、jmeter 的压力测试工具,官方称它为:现代的 HTTP 基准测试工具
  • 用 C 编写的 HTTP 协议压测工具
  • 底层基于 epoll 和 kqueue 实现,使用了多线程和多路复用 IO(非阻塞 IO),利用异步的事件驱动框架,通过很少的线程就可以压出很大的并发量
  • 降低测试工具本身性能开销对测试结果准确性的影响
  • 支持使用 LuaJIT 脚本,可以执行 HTTP 请求生成、响应处理和自定义报告

 

它的定位


  • 轻量级性能测试工具
  • 仅支持 HTTP 协议
  • 仅支持单机压测,多机器压测需要每个机器都手动执行一次 wrk 命令
  • 不可取代 Jmeter、LR 等专业性能工具

 

架构&简单源码解析


image.png

  • 在 wrk 里面,每个线程都有自己独立的 Lua 虚拟机和 Event Loop
  • 通过命令行参数 -c 指定的连接数,会平均分给所有线程,每个新建的 socket,都会调用 fcntl 将其设置为 NONBLOCK,即非阻塞,然后托管给 Event Loop
  • 直接使用 redis 的 Event Loop 实现,适配了不同操作系统的实现
  • 启动的时候,每个线程都会新建一个 Lua State,并调用 luaL_dofile 加载命令行参数 -s 指定的 lua 脚本文件
  • 如果没有自定义的 lua 脚本,wrk 默认发送的是 HTTP 1.1 GET 请求,用长连接

 

语法格式


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:与服务器保持的 http 连接数
  • -d:压测持续运行时间,可以是 2s、2m、2h
  • -t:启动的线程数
  • -s:指定 lua 脚本
  • -H:自定义 http header 请求头,例如:"User-Agent: benchmark-wrk"
  • --latency:打印延迟统计数据
  • --time:http 超时时间,如果在此时间内未收到响应,则当做超时

 

数字参数:可以使用 1k、1M、1G 单位

 

-t

  • 一般是 CPU 核数,最大不要超过 CPUx2 核数,否则会带来额外的上下文切换,将线程数设置为 CPU 核数主要是为了 WRK 能最大化利用 CPU,使结果更准确(截取网上,暂时没看到官方推荐)
  • 和并发数没有直接关系
  • 查看 Linux CPU 总核数:

grep processor /proc/cpuinfo |wc -l

 

-c

  • 连接数(connection)可以理解为并发数
  • 一般在测试过程中,这个值需要使用者不断向上调试,直至 QPS 达到一个临界点,便可认为此时的并发数为系统所能承受的最大并发量
  • 实际上,wrk 会为每个线程分配(c/t)个 socket 连接
  • 每个连接会先执行请求动作,然后等待直到收到响应后才会再发送请求,所以每个时间点的并发数大致等于连接数(connection)

 

官方 Tips


  • 运行 wrk 的机器必须有足够数量的临时端口可用,关闭的 socket 必须快速回收
  • 仅更改 HTTP 方法、路径、添加请求头或正文的用户脚本不会对性能产生影响
  • 每个请求的操作,特别是构建新的 HTTP 请求,以及 response() 的使用将必然减少可以生成的负载量

 

简单栗子


启动 2 个线程,保持 5 个 http 连接打开的状态下,持续压测 10s 的基准测试

wrk -t2 -c5 -d10s https://httpbin.org/get

image.png

qps 是 14.85

 

启动 16 个线程,保持 400 个 http 连接打开的状态下,持续压测 5s 的基准测试,并打印延迟统计数据

wrk -t16 -c400 -d5s --latency https://httpbin.org/get

image.png

qps 是 578.7

 

结果解析

Running 5s test @ https://httpbin.org/get   压测时间5s
  16 threads and 400 connections   共16个测试线程,400个连接,和上参数设置一样
  Thread Stats   Avg      Stdev     Max   +/- Stdev
                平均值    标准差     最大值  正负标准差的范围,越大表示值和平均值不会差很多,离散也不大,表示 Avg 相对可信
    Latency   311.74ms  211.97ms   1.57s    90.79%
    延迟
    Req/Sec    47.86     31.17   170.00     66.79%
    每个线程每秒的完成的请求数
  Latency Distribution 延迟分布
     50%  234.77ms
     75%  244.43ms
     90%  402.99ms
     99%    1.26s     99% 的请求在 1.26s 内完成
  2938 requests in 5.08s, 1.21MB read  5.08 s内共处理完成了 2938 个请求,读取了 1.21MB 数据
  Socket errors: connect 166, read 0, write 0, timeout 1   Socket 成功连接 166个,超时 1 个
Requests/sec:    578.70  平均每秒处理完成 578.7 个请求,QPS=578.7
Transfer/sec:    243.05KB  平均每秒读取数据 243.05KB


-t 的一些实验


测试资源

  • 施压机:16c32g
  • 受压机:8c16g

接下来对某个接口进行基准测试

 

16 个线程,400个并发量,持续运行 5min

image.png

qps:20504.3

 

64 个线程,400个并发量,持续运行 5min

image.png

qps:19948.69

 

128 个线程,400个并发量,持续运行 5min

image.png

qps:18811.35

 

结论

  • 线程数增加,qps 反而下降
  • 初步可以认为,-t 线程数取系统 CPU 核数是一个比较靠谱的建议
相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
相关文章
|
测试技术 C语言
wrk(2)- Lua 脚本的使用
wrk(2)- Lua 脚本的使用
865 0
wrk(2)- Lua 脚本的使用
|
监控 网络协议 Java
Jmeter系列(35)- 使用 ServerAgent 监控服务器
Jmeter系列(35)- 使用 ServerAgent 监控服务器
587 0
Jmeter系列(35)- 使用 ServerAgent 监控服务器
|
缓存 前端开发 应用服务中间件
Nginx开启Gzip压缩功能(附详细解释)+测试是否开启了压缩
Nginx实现资源压缩的原理是通过ngx_http_gzip_module模块拦截请求,并对需要做gzip的类型做gzip,ngx_http_gzip_module是Nginx默认集成的,不需要重新编译,直接开启即可。
2890 1
Nginx开启Gzip压缩功能(附详细解释)+测试是否开启了压缩
|
NoSQL 测试技术 Apache
wrk | 虽小但强!
wrk | 虽小但强!
196 0
|
开发者
Cypress系列(68)- request() 命令详解
Cypress系列(68)- request() 命令详解
427 0
Cypress系列(68)- request() 命令详解
|
Python
Cypress系列(70)- server() 命令详解
Cypress系列(70)- server() 命令详解
195 0
Cypress系列(70)- server() 命令详解
Cypress系列(73)- within() 命令详解
Cypress系列(73)- within() 命令详解
280 0
Cypress系列(73)- within() 命令详解
Cypress系列(80)- setCookie() 命令详解
Cypress系列(80)- setCookie() 命令详解
146 0
Cypress系列(80)- setCookie() 命令详解
|
JavaScript
Cypress系列(76)- cloest() 命令详解
Cypress系列(76)- cloest() 命令详解
336 0
Cypress系列(76)- cloest() 命令详解
|
JSON 数据格式
Cypress系列(95)- writeFile() 命令详解
Cypress系列(95)- writeFile() 命令详解
244 0
Cypress系列(95)- writeFile() 命令详解