找回密码
 注册
查看: 3365|回复: 2

高性能 Http 压测工具 wrk 的使用,wrk2入门-http性能压测工具总结

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2020-11-11 17:00:13 | 显示全部楼层 |阅读模式

wrk 是一种高效的 HTTP 基准测试工具,能够在单个多核 CPU 上运行时产生大量负载。它将多线程设计与 epoll 和 kqueue 等可伸缩事件通知系统相结合。因此,使用 wrk 使用较少的线程即可以压测出非常可观的请求数据。

并且我们可以通过一个可选的 LuaJIT(Lua) 脚本来提供更多的请求参数的定制,参数加密、鉴权请求等。

基础使用( Y, [/ v! q+ a5 I5 C9 H
使用类 Unix 环境,在 CentOs 或 MacOs 上进行测试

wrk 开源 GitHub 地址: https://github.com/wg/wrk- |1 `9 Z: m& V5 O
通过 git clone 的形式下载 源码包,进入目录下,执行 make ,然后开始编译安装,等待一会即可完成。

wrk 使用参数说明
, u6 k# p( u% S2 r& x2 ?-c, --connections:  总的连接数(每个线程处理的连接数=总连接数/线程数)
. S9 ~. k0 \2 u+ t7 K-d, --duration:        测试的持续时间,如2s(2second),2m(2minute),2h(hour): I; K1 G; ?- y+ b( v/ _% P
-t, --threads:         需要执行的线程总数
9 V) I. W% ]8 J6 \" L: V2 j-s, --script:          执行Lua脚本,这里写lua脚本的路径和名称,后面会给出案例6 U! _/ L0 Y( C1 y
-H, --header:      需要添加的头信息,注意header的语法,举例,-H “token: abcdef”,说明一下,token,冒号,空格,abcdefg(不要忘记空格,否则会报错的)。
# {: P0 z, N0 F) I  l' l--latency:     显示延迟统计信息
6 B: K- P6 m: q/ O6 K--timeout:     超时的时间& _: L4 k( ^0 b$ B4 ?$ c$ f
例子4 ]8 k4 C: b% C; p6 ?. I, X: `. A
wrk -t12 -c400 -d30s http://127.0.0.1:8080/index.html" o3 F( F5 |& x  K5 T7 U; ^
该请求意思为: 使用 wrk 使用12个线程,400个连接,请求 url 30s

压测结束后的结果:
1 G; w; o+ M+ M8 b/ c* V( ^( z7 qRunning 30s test @ http://127.0.0.1:8080/index.html2 }0 d. r+ ^9 h& @0 o
  12 threads and 400 connections1 ]4 V) r+ q* H( E
  Thread Stats   Avg      Stdev     Max   +/- Stdev7 N4 g+ D4 P. i% M
    Latency   635.91us    0.89ms  12.92ms   93.69%
1 w' q% q/ ~9 g+ Z$ C  V    Req/Sec    56.20k     8.07k   62.00k    86.54%
1 d8 v' |& h! g% M6 e  22464657 requests in 30.00s, 17.76GB read) \: p, I+ c  ]8 k+ c# P
Requests/sec: 748868.536 s# ~4 _+ b: c6 y. X
Transfer/sec:    606.33MB
% I6 ^7 U% f, [' P9 J( v返回结果说明:

Latency:响应时间Req/Sec:每个线程每秒钟的执行的连接数
/ R+ q; T3 ~) A% G% P, SAvg:平均
5 l8 [9 l) U2 FMax:最大
- q" W  U% P* m& s; JStdev:标准差+/- Stdev: 正负一个标准差占比7 H7 v. x( W. c( O8 Q, H- f* ~# w- o
Requests/sec:每秒请求数(也就是QPS),这是一项压力测试的性能指标,通过这个参数可以看出吞吐量
- m0 Q# l4 F/ G% E9 FLatency Distribution,如果命名中添加了; A$ t$ Y1 _( w3 U
latency就会出现相关信息% t5 O* n) ^1 e; P3 L) W
实战
( K4 N3 ^; |0 [" U  ?, L使用 wrk 对鉴权的接口进行调用压测。由于是鉴权的接口,需要根据密钥和时间戳动态的生成 secret 然后对后端进行请求,才能通过验证。这里我们引入 lua 脚本
3 e) N" z2 O8 P" c5 C# Y# J由于 wrk 工具里面 自带 luaJit ,所以我们不用下载。但是需要 md5 的模块,所以需要使用 luarocks 来管理和下载 lua 模块和包。

安装Luarocks 包管理工具+ y' T$ a9 M  _6 [+ j; c% c' |
LuaRocks 是 Lua 模块的包管理器。它允许您将 Lua 模块创建并安装为自包含包(称为 rocks )。您可以在 Unix 和 Windows 上下载和安装 LuaRocks。官网:https://luarocks.org/

通过 curl 下载8 a3 M4 h& i' B' B! F) O6 V
curl -o luarockt-3.0.3.tar.gz http://luarocks.github.io/luarocks/releases/luarocks-3.0.3.tar.gz
7 {( C, ?0 w9 x, C$ T解压 luarockt-3.0.3.tar.gz后,进入目录下 指定到 wrk 里 LuaJit 的目录进行 configure

//这里指定你自己的 `wrk` 路径
" V" N: D' C1 m. m./configure --with-lua=../wrk/obj. T% F" c4 K% j; Z  \% c2 I# Q; B
编译安装
! ?5 E3 x) j$ b1 Umake install
) o  ]! z2 h1 f. h+ G通过 Luarocks 安装 md5 模块
" g6 Y$ S* m+ m- V# M2 D' ^1 bluarocks install md5

开始请求
* a/ N3 s- s' Y: `我们需要像 url http://127.0.0.1:9000 网关进行 POST 请求,该网关会对请求进行鉴权和验证,并判断请求的实效性。所以我们需要在请求时动态改变请求参数,因此需要结合 Lua 脚本。

Lua 脚本 helloDemo.lua- M' i3 T; J# g: V% e
md5=require("md5")7 A* h  V$ e2 Y, `! i- i
-- md5加密,拼接请求对象- i1 v6 m* I) D  x0 G8 n- L% u
function buildJson(json)
# v( U  N+ C4 h3 E. _1 H7 l  local apiKey = "abcdefg1234567"% j. z4 V) f& Q: X4 c% u4 ~
  local password = "qwerxxxx") r6 Y: R  g8 k
  local timestamp = os.time() .. "000"
: ]) e" H8 E/ j; |# }4 B- E8 C  local secret = md5.sumhexa(apiKey .. timestamp ..  password)0 N4 o4 ?% X0 n
  local body = json .. "×tamp=" .. timestamp .. "&secret=" .. secret* B9 p3 z% e6 S/ [' V
  
1 Y0 N$ H9 J$ K5 I9 u# N7 x- J9 \" z  return body) K, ^, Q: r  c( V$ c: {
end

wrk.method = "POST"
, |! G" y1 a8 d0 f+ y6 j! @wrk.body = buildJson("serviceName=com.github.dapeng.service.HelloService&version=1.0.0&methodName=sayHello¶meter={\"body\": {\"request\": {\"bizTag\": \"order\", \"step\": 100}}}")
4 m3 x" ]# k- j2 ~5 m* swrk.headers["Content-Type"] = "application/x-www-form-urlencoded"" r2 c7 j. W5 o2 ]8 u  p7 s
请求脚本

#!/usr/bin/env bash
7 r( }# `$ X& o' ptime1=`date +%s`
' @4 [! u! |6 ^6 g7 Recho "开始时间 `date +%Y%m%d%H%S`"% I1 w: {# r& I* x! m( k: T/ l
# wrk 安装目录 -s 后指定上面写好的lua脚本
, R: X( t; H/ _2 Y~/ideaspace/dapeng/benchmark/wrk/wrk -t4 -c400 --timeout 5s -d 60s -s lua/$1.lua --latency 'http://127.0.0.1:9000/api/e1bfd762321e409cee4ac0b6e841963c'( P% i( s7 Z$ [
time2=`date +%s`
7 b1 I- t$ A4 H7 euseTime=$[time2 - time1]& o5 F4 }7 T* i
echo "结束时间 `date +%Y%m%d%H%S`"$ n$ `8 K+ O; v# N" n0 T
echo "总共花费 $useTime s": _8 U& d( @& Q. p
执行脚本

sh start-wrk.sh helloDemo- o. M5 q# u- @5 b
通过上面方式,我们就可以开始请求已鉴权的接口

总结( i( u1 \; J# @
wrk 是一款高性能的 http 请求压测工具,它使用了 Epoll 模型,使所有请求都是异步非阻塞模式的,因此对系统资源能够应用到极致,可以压满 cpu。4 o- _1 u! {$ c" o+ Z# R" ?" g+ [9 S
wrk 可以落站使用 Lua 脚本。该特性可以使我们通过 脚本动态的改变请求参数,对请求压测提供的多样性的选择和定制。

后续
" \, O% B, ]+ w4 B: }* ~9 L' L1. 去除 CO* ^1 q' Q2 H; f* _$ s- q
关于 wrk 测试延迟分布不准确的问题,涉及到 Coordinated Omission 的原因,可 Google
0 j% p. }, N3 D, K5 G在 src/wrk.c9 Z& A  Y/ w" c2 S% H4 m% V: {! R
将下面部分代码注释:& g. `* p: C' p: n2 T* [- A
//  if(complete / cfg.connections > 0) {" j8 q' q, {' f4 E
//       int64_t interval = runtime_us / ( complete / cfg.connections);
: e, d% B$ p( t& z$ [8 J//       stats_correct(statistics,latency,interval);
6 V: j) L# `) g# e- \7 P关于 wrk 测试延迟分布不准确的问题,涉及到 Coordinated Omission 的原因,可 Google,也可以参考 wrk2

+ M/ y' n9 v5 ^8 E/ P6 k+ H. i( z
7 j) `4 K) G8 g) E1 D
wrk入门总结4 z. P& P# J, f3 Q8 z5 h

# b- u, Y1 y; C" M; l一、功能介绍:

  wrk2是一个主要基于wrk的HTTP基准测试工具,wrk2经过修改后能够提供稳定的吞吐量负载以及更精确的延时统计,即通过设置参数,wrk2增加了–rate或-R参数设置吞吐量(每秒总请求数)及–u_latency参数显示延时统计。

二、安装过程:

wrk安装过程非常简单,下载源码后在项目目录下执行make命令即可。

2 Y. L% E& H2 M7 Z6 H
  • make编译过程中问题解决:

    1. -bash: make: command not found

    [root@XXX wrk2-master]# make-bash: make: command not found) Z# T9 A+ @2 _9 t7 j8 }

+ y7 _) t! V, n# N

  系统无法使用make,make install,一般出现== -bash: make: command not found ==的提示,是因为安装系统的时候使用的是最小化安装,缺少make、vim等常用命令。
# H9 `8 G4 G% M- _4 y- Z2 c  直接安装make即可解决问题:

[root@XXX wrk2-master]#yum -y install gcc automake autoconf libtool make7 M6 `, K. p/ D7 L$ T1 R% J

3 W- \' e. ?+ w/ K- m! |3 H

  安装g++:

[root@XXX wrk2-master]#yum install gcc gcc-c++9 |: ]* u( {9 r4 x

/ @7 \- c6 K0 B, B: G' {

2. src/wrk.h:11:25: fatal error: openssl/ssl.h: No such file or directory0 \4 I' D8 L9 C3 H$ ^: q# ]
https://img-blog.csdnimg.cn/2020052220505566.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NjY2NzeTk5,size_16,color_FFFFFF,t_70: y4 V2 s3 j9 L6 u: ?. m
  问题在于:系统中缺少openssl库,安装即可

[root@XXX wrk2-master]# yum install openssl-devel  或者[root@XXX wrk2-master]# yum install libssl-dev! x3 ?% \2 O* _

& [9 r* O' `& D9 u. D; q! p' q三、wrk 初步使用
  • 基本用法:

    Basic Usage: wrk <options> <url>

    Options:                                                -c, --connections <N>  Connections to keep open( Q7 G. n2 q9 |; n" a- b
     # HTTP连接数,如1k,1M,1G,    -d, --duration  <T>  Duration of test  . @; _, D$ R% j2 `$ W
    # 测试持续时间,如 2s 2m 2h              -t, --threads <N>  Number of threads to use  8 J! U; N# o) I; J7 ~! t
    # 开启的线程数                                                           -s, --script   <S>  Load Lua script file " J1 j* V. R8 ^2 V
  # 进阶功能,使用 lua 脚本    -H, --header   <H>  Add header to request  
1 x4 n; }1 G5 i, C; R) T  # 添加请求头                    # x3 W0 L0 d7 u2 C. J
# 打印详细延迟统计    -L  --latency    Print latency statistics       -U  --u_latency  Print uncorrceted latency statistics                     ==
8 w" P0 Z- ], y& O% K# 设置请求超时时间,大于该时间的请求将被记录==          --timeout     <T>  Socket/request timeout         -B, --batch_latency    Measure latency of whole                              batches of pipelined ops                              (as opposed to each op)        -v, --version          Print version details          -R, --rate        <T>  work rate (throughput)   
* [. M2 b  [% G( r& r#工作速率(吞吐量)即每个线程每秒钟完成的请求数                           in requests/sec (total)                               [Required Parameter]
! D- s7 |/ m9 d; R; G4 K) x, g# M6 G6 _, I; g1 V4 G" I
  • 使用方法–readme/ m5 i2 M' X) o2 C4 i
[td]
使用方法说明吞吐量/每秒总请求数
wrk -t2 -c100 -d30s -R2000 http://127.0.0.1:8080/index.html2个线程,100个连接,持续时间30s 每秒2000个请求Requests/sec: 2000.12
wrk -t2 -c100 -d30s -R2000 --latency url2个线程,100个连接,持续时间30s,每秒2000个请求延迟标识,延迟百分比

$ t& f) d* G3 u" s& @1 H四 测试场景
  • 测试HTTP协议网络的性能[root@XXX scripts]# wrk -t2 -c1000 -d15 -R1000 --latency https://www.baidu.com/
    ; d0 v1 P( t$ g8 C  n) c& F' z; J8 ]
    • 1
      & g% n9 q/ c, `2 F1 j% O
    Running 15s test @ https://www.baidu.com/    ------压测时间15s  2 threads and 1000 connections                         -------共2个测试线程,1000个连接  Thread calibration: mean lat.: 24.071ms, rate sampling interval: 41ms  Thread calibration: mean lat.: 24.373ms, rate sampling interval: 40ms  Thread Stats   Avg      Stdev     Max   +/- Stdev     -----平均值 标准差 最大值 正负一个标准差所占的比例    Latency    13.10ms    5.09ms 124.16ms   95.55%  -----延迟    Req/Sec   449.03    706.21     5.15k    94.26%        -----处理中的请求数  Latency Distribution (HdrHistogram - Recorded Latency)   -----延迟分布 50.000%   12.34ms 75.000%   13.68ms 90.000%   15.83ms                  -----90分位的延迟 99.000%   21.14ms                   ----99分位的延迟 99.900%  107.97ms 99.990%  124.22ms 99.999%  124.22ms              100.000%  124.22ms#[Mean    =       13.101, StdDeviation   =        5.093]#[Max     =      124.160, Total count    =         2201]#[Buckets =           27, SubBuckets     =         2048]----------------------------------------------------------  13795 requests in 15.00s, 206.31MB read   ----15s内共处理完成了13795个请求,读取了206.31MB数据Requests/sec:    919.62                                     -----平均每秒处理完成919.62个请求Transfer/sec:     13.75MB                                   -----平均每秒读取数据13.75MB
- [$ z% y8 _) R6 A8 N; |7 R$ i

  压测简单说明:以上使用了2个线程1000个http连接,对baidu进行了15s的压测,并要求在压测结果中输出响应延迟信息。

  • 测试当前服务的最大QPS

      进入安装目录,运行


    7 P8 P0 w% q' F# |
[td]
通过-R参数获取吞吐量参数每秒请求量的结果
./wrk2 -t10 -c50 -d30 -R3000 -H “Host:xxx.com” http://localhost/a/a.mp4 -LRequests/sec: 3000.12
./wrk2 -t10 -c50 -d30 -R5000 -H “Host:xxx.com” http://localhost/a/a.mp4 -LRequests/sec: 5000.12
./wrk2 -t10 -c50 -d30 -R10000 -H “Host:xxx.com” http://localhost/a/a.mp4 -LRequests/sec: 9800.12
./wrk2 -t10 -c50 -d30 -R20000 -H “Host:xxx.com” http://localhost/a/a.mp4 -LRequests/sec: 12500.12
./wrk2 -t10 -c50 -d30 -R30000 -H “Host:xxx.com” http://localhost/a/a.mp4 -LRequests/sec: 13000.12
' ^( h6 g, Q7 ^' N

从以上的测试过程中可以看出,服务最大的每秒请求量为13000,可见性能压测的QPS为1.3万左右,考虑本机测试性能损耗问题,即QPS>1.2万

  • 使用Lua脚本个性化wrk压测
    ' o, J6 @# U3 F% P+ S( x

  以上是介绍wrk的安装及简单的使用,可以看出wrk的使用较简单方便,且测试结果清晰,一般情况下关注的指标主要是:90分位延迟、99分位延迟及Requests/sec。但是工作上往往需要较复杂的测试场景,这种简单的压测可能就不满足需求。比如,使用POST 方法跟服务器交互;每次请求使用不同的参数;为了更好的模拟服务场景,需要使用wrk的script lua脚本来定制压测过程,即满足定制化的需求。+ v$ Q6 V8 \5 t& d; @' Z
  有关wrk高级使用方法,可以查看我的另一篇博客:wrk2的高级使用方法

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2020-11-11 17:00:14 | 显示全部楼层
软件简介) F6 M& ?7 X# O
wrk 是一个比较先进的 HTTP 压力测试工具,当在单个多核 CPU 上运行时,能够产生大量负载。它结合了多线程设计和可扩展的事件通知系统,例如 epoll 和 kqueue。, L& o: d% C# t+ P$ o

# P  D2 j- O& G7 m5 l8 v可选的 LuaJIT 脚本可以执行 HTTP 请求生成,响应处理和自定义报告。
& R3 @1 E% C; I. ~2 G
+ l# d/ Y9 \( p3 v/ u& r/ _- M测试方法:2 t; q4 O+ r6 {1 Z- Q
& f* G& U1 m3 d0 u0 Z
wrk -t8 -c400 -r10m http://localhost:8080/index.html- n! Q% C5 q# n2 {/ ?: z" C5 ?: H
输出结果:
6 z" o* ~8 b9 m+ s; ^# r, i0 H
/ h! T$ N) z& V4 ?, G4 z% H  Making 10000000 requests to http://localhost:8080/index.html
* B7 P7 v) X# o7 y2 p7 t    8 threads and 400 connections
5 ?6 ?7 `4 n2 R4 X% c! f0 \) z    Thread Stats   Avg      Stdev     Max   +/- Stdev: T# j2 o0 |: k; |" w, {
      Latency   439.75us  350.49us   7.60ms   92.88%
6 }4 ?$ W- ^, g* C( L      Req/Sec    61.13k     8.26k   72.00k    87.54%% Y0 H* ~1 `2 Q4 K5 }
    10000088 requests in 19.87s, 3.42GB read
& D6 q9 c4 d2 C4 l& Y  B! w  Requests/sec: 503396.23
; C; ^" Z; P2 \  o- r1 b8 Z  Transfer/sec:    176.16MB6 c* a2 ^% S3 d$ a* a

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2020-11-11 17:00:15 | 显示全部楼层
一、简介* u+ W8 ^# \8 q; M) m; w, ]
1 |: z% g2 p! z9 V* P( H3 h" J/ ]
  wrk 是一款针对 Http 协议的基准测试工具,它能够在单机多核 CPU 的条件下,使用系统自带的高性能 I/O 机制,如 epoll,kqueue 等,通过多线程和事件模式,对目标机器产生大量的负载。$ @5 L, W8 E( H- Y! C1 r1 ?7 b
. W1 I2 e# }6 a0 k
wrk是开源的, 代码在 github 上:https://github.com/wg/wrk# H% v, L* }$ z
1 C5 D5 y! V4 J/ A& J3 v
安装:https://www.cnblogs.com/savorboard/p/wrk.html
  d3 X2 K4 Z. f" h: v$ L
0 |# j$ F% A. a  `5 k) W
$ e2 Z- Z* x" O
8 D+ g$ B$ C+ f4 U2 C8 ~优势:
9 Q, F  C7 B% n2 f' B9 B: I; p9 h" U
轻量级性能测试工具
/ R! n2 q& i) l0 B安装简单
# \9 A1 `2 e; V4 x5 e2 \( `学习曲线基本为0,几分钟就学会使用了( C( M- P6 O4 [$ V$ z0 p
基于系统自带的高性能I/O机制,如epoll,kqueue,利用异步的事件驱动框架,通过很少的线程就可以压出很大的并发量,例如几万、几十万,这是很多性能测试工具无法做到的。
2 L1 z- _1 ?. B9 @5 O& f0 I劣势:
* L( @4 v6 a% K( W( O' m
, o4 E4 z8 m# T9 @* I+ ~wrk 目前仅支持单机压测,后续也不太可能支持多机器对目标机压测,因为它本身的定位,并不是用来取代 JMeter, LoadRunner 等专业的测试工具。
' h1 D( n3 S8 L+ w6 z2 i5 N
. N; b6 P8 h0 X. V; L5 Q) }5 `$ K5 B) U- k& R+ @; |
二、格式及用法
: O9 t3 N) `+ T& h* K7 m
8 C: {8 S& U, b1 V3 Z9 m# l复制代码
% A7 S' S( p. @8 @, F/ ^2 c% JUsage: wrk <options> <url>                           : e" f3 R; M$ w3 S
( N- b6 A! r8 X3 d% f% w* j2 `
  Options:                                          
7 a6 [6 o$ ?' a    -c, --connections <N>  Connections to keep open  . k: K& y, R9 J2 l+ h6 v
    -d, --duration    <T>  Duration of test         
: a8 F0 X5 p4 T+ J0 F    -t, --threads     <N>  Number of threads to use  
5 b) b& F/ r5 j' h+ w                                                     5 m$ \* C, p; `9 t; j* U% @
    -s, --script      <S>  Load Lua script file      ! |5 t/ s, A( ]. j9 I5 p- h6 _
    -H, --header      <H>  Add header to request     
9 p8 P6 R4 x4 I2 R6 m" B5 I        --latency          Print latency statistics  * `1 M5 K2 B5 g
        --timeout     <T>  Socket/request timeout   
* [5 `1 P; t& y' o6 S$ C    -v, --version          Print version details     - L8 t9 n- n' g) x6 S7 ]! K7 |
                                                
" u% a8 ]  M5 X" ^& d4 X  Numeric arguments may include a SI unit (1k, 1M, 1G)
6 s' k/ q; d5 N1 Q9 @6 X  Time arguments may include a time unit (2s, 2m, 2h)) A4 B+ J, n& v5 j6 `! V$ B  \
复制代码; \* ]4 d  f& k2 \% }) K5 b
+ R- P$ Q3 a4 l  e' T

9 o: R% x% R$ L  I翻译成中文:
7 t% L) r6 V) [, g' E
! s' Q4 m# @4 U2 I' x6 w复制代码
% ^" g7 }' `' Z$ ]0 V使用方法: wrk <选项> <被测HTTP服务的URL>                           5 e% J' S. W- W" ?) r

: b8 X. m$ a' s9 M  Options:                                           * @5 z# ~% [& V. i6 k9 w
    -c, --connections <N>  跟服务器建立并保持的TCP连接数量
. O. B) u( d3 _8 J( x    -d, --duration    <T>  压测时间          6 o: l( S5 A( U1 z
    -t, --threads     <N>  使用多少个线程进行压测,压测时,是有一个主线程来控制我们设置的n个子线程间调度  
3 `7 u: @0 L! [. i* I0 e  C                                                   
6 n9 `6 [0 c  P+ v2 Y) J- v8 X+ E6 M    -s, --script      <S>  指定Lua脚本路径      7 G! a! {# A) M+ h$ M
    -H, --header      <H>  为每一个HTTP请求添加HTTP头     / q* Z; ]4 t- U
        --latency          在压测结束后,打印延迟统计信息  ! B$ X$ e  c% s* v0 o4 F
        --timeout     <T>  超时时间   
) e2 C0 M/ h3 q    -v, --version          打印正在使用的wrk的详细版本信                                              6 o  z, f: g: x& I& T

' H- [) r9 S. D, I0 X3 w0 o/ e) w  <N>代表数字参数,支持国际单位 (1k, 1M, 1G)7 y, K$ J" w9 k% J
  <T>代表时间参数,支持时间单位 (2s, 2m, 2h)1 a, }/ u% @2 V7 ~4 L* n; q- l
复制代码
5 O( P1 G7 m0 W* m$ j
  S+ U8 w; |, R* d3 v% V- Z* r
, ]% J8 {) u, t) p
8 V0 D: {9 b( r( d) m6 D" _* _
4 H8 p8 E1 F& l4 ~% K三、简单压测及结果分析
; I; L+ y7 Q9 b- G( v+ ~5 M7 X. }& W' N' O, ~1 `( O
做一个简单的压测,分析下结果:0 l8 y9 o  K8 Q" c& c- Q9 G

# {' O- o) F9 p; }8 Qwrk -t8 -c200 -d30s --latency  http://www.bing.com/ K5 O) b6 g  |. s/ S

- Y3 g! Y9 e; P1 q- F
( f8 a. U: n; n$ v, p7 ?. F输出:
; w( S3 s  d; H! t) m% U5 p  {& i- P
复制代码( ]4 }7 @  u0 ?1 Z4 [0 L
Running 30s test @ http://www.bing.com
: X4 w! H, [) R- X! @
: Y' X2 F1 D+ u& G+ b' Y, z8 J( o) ]# l  8 threads and 200 connections, U3 B3 J0 [3 W; \! a! C0 v
( c2 j$ M, z6 Y# x0 ^( _. v! a
  Thread Stats   Avg      Stdev     Max   +/- Stdev* s: H9 }3 `6 @& X  D" [( M
    Latency    46.67ms  215.38ms   1.67s    95.59%& \% A4 B- w, b4 w
    Req/Sec     7.91k     1.15k   10.26k    70.77%
( S+ F* B4 W0 @1 v" i- c9 a2 s
  Latency Distribution
9 G  D/ `1 _0 H     50%    2.93ms
# ]$ ]4 \5 `& z9 x0 \! ?, i     75%    3.78ms
0 y- h/ X/ L, }3 _; ^. y     90%    4.73ms
& Z  r. H8 G2 _! }: M: }# V9 o     99%    1.35s9 m7 ^: G9 ~1 e1 R" |
  1790465 requests in 30.01s, 684.08MB read4 A0 d; t2 t2 B6 Y
Requests/sec:  59658.29  J/ |  r+ k* a2 \7 `, X
Transfer/sec:     22.79MB
2 ~/ U* N5 z' D/ t9 Q复制代码
- w" e! n% @; \. G0 s0 a, }. S* h以上是使用8个线程200个连接,对bing首页进行了30秒的压测,并要求在压测结果中输出响应延迟信息。
1 a6 u8 r2 h) N2 I$ E) ~  A4 A: U2 c3 R
以下是解释压测结果:0 I$ e" d- U8 ^- I

1 C8 W# `- @, U% G% e复制代码
2 v! k  H# x$ ~6 @8 ^' p/ iRunning 30s test @ http://www.bing.com (压测时间30s)" s$ O: S1 H6 k% G

: d4 g# b; T# h  8 threads and 200 connections (共8个测试线程,200个连接)
% \: p( D% b8 N; h& Q" b8 ]1 e6 k  q' G
  Thread Stats   Avg      Stdev     Max   +/- Stdev) P5 G8 b9 S; t
              (平均值) (标准差)(最大值)(正负一个标准差所占比例)
1 A8 `: `; |* {    Latency    46.67ms  215.38ms   1.67s    95.59%
0 Q; @, O- P8 @2 w' n, Q    (延迟)
& j& P, ~; R1 M7 p  F( ^    Req/Sec     7.91k     1.15k   10.26k    70.77%& R5 u8 |! I" s. b
    (处理中的请求数)1 P" K0 H8 k7 V4 f3 z& ?

2 O. X& _/ Y# ^, H  Latency Distribution (延迟分布)
/ y2 ~* v9 f5 f; q+ N' q/ g     50%    2.93ms
4 c$ A6 |- c/ k+ M9 n     75%    3.78ms
  Y* P0 C. z0 S/ z# `     90%    4.73ms3 J# P" M; k9 G. j( H) D
     99%    1.35s (99分位的延迟:%99的请求在1.35s以内)  _8 l0 a  @# R! c' l
  1790465 requests in 30.01s, 684.08MB read (30.01秒内共处理完成了1790465个请求,读取了684.08MB数据)
* x9 W3 Y' p5 e2 O2 W* F, TRequests/sec:  59658.29 (平均每秒处理完成59658.29个请求)# o' ], c: y. x7 M$ E. ^& R
Transfer/sec:     22.79MB (平均每秒读取数据22.79MB)
" C% C! i* W7 @6 _% l/ }" G复制代码
0 x. V9 f! J0 g, a - S% ?7 ?. y5 L( `9 O

: E( y" E; {: S4 N - f2 m4 w. t8 ~- j. Y1 f

# Q8 |" {' s2 X8 N, k& L2 K四、使用lua脚本进行压测
2 z( c: f8 A7 i: H- G+ `7 j, l, ^& u' n
  lua脚本是一种轻量小巧的脚本语言,用标准c语言编写,并以源代码形式开放,其设计目的是为了嵌入应用程序中,从而为程序提供灵活的扩展和定制功能。wrk工具嵌入了lua脚本语言,因此,在自定义压测场景时,可在wrk目录下使用lua定制压测场景。
* y* t' M' N8 B5 n7 v4 b2 [. E8 O
' ^7 A+ _: t7 ]8 Z% X  1、lua声明周期# S; F. a& E1 M6 w3 t: p7 f( g

4 h& n$ w0 O6 @' W- n3 N    共有三个阶段,启动阶段,运行阶段,结束阶段。wrk支持在这三个阶段对压测进行个性化。   8 D# i- w7 B, f% d2 i. [4 Y  W

0 D2 y  g) H$ e6 r/ @启动阶段" K' ?$ n1 Q: `7 e  U
function setup(thread)
( R0 s) W0 ^) u  l- v* r( E
' X% k* d# |* W- T/ u# l
$ f: o6 b) E  t" w9 N在脚本文件中实现setup方法,wrk就会在测试线程已经初始化但还没有启动的时候调用该方法。wrk会为每一个测试线程调用一次setup方法,并传入代表测试线程的对象thread作为参数。setup方法中可操作该thread对象,获取信息、存储信息、甚至关闭该线程。
% W( ~* V5 U: P% n; Z6 m1 r% d/ z6 R# p7 G1 T3 Z
thread.addr - get or set the thread's server address& p0 i  `2 {4 i0 {4 @1 P
thread:get(name) - get the value of a global in the thread's env
% t1 ]2 d4 {) C  N% B1 Ethread:set(name, value) - set the value of a global in the thread's env
+ J. w( T1 y) H; P' Y% A) nthread:stop() - stop the thread& A( D7 S9 ?* l: Q) u
* |0 N" p/ |2 M# G
0 m6 }1 Q$ q7 q' l
运行阶段
2 m/ ?1 t% _7 ffunction init(args)  --由测试线程调用,只会在进入运行阶段时,调用一次。支持从启动wrk的命令中,获取命令行参数;
; d/ b& U* ]6 l6 t+ |function delay()  --在每次发送request之前调用,如果需要delay,那么delay相应时间;
) K/ M2 Y+ m1 i6 n% Efunction request()  --用来生成请求;每一次请求都会调用该方法,所以注意不要在该方法中做耗时的操作;" \& {# ?: d& |  P% c
function response(status, headers, body)  --在每次收到一个响应时调用;为提升性能,如果没有定义该方法,那么wrk不会解析headers和body;# Z2 {0 S. G! Q; [

+ h' N# Q) c' D* W* F3 B/ m8 R' p3 O( q5 _0 q
结束阶段6 N2 v3 g( y8 K" z3 D' u1 r, {
function done(summary, latency, requests)  --在整个测试过程中只会调用一次,可从参数给定的对象中,获取压测结果,生成定制化的测试报告。
/ L6 e" q/ D2 k   
4 @3 L+ f1 w2 y$ `' x
. J* {5 |& e/ d' g+ s  2、自定义脚本中可访问的变量和方法:9 w' y0 Z% I1 T" s+ L( L
3 c2 V2 b) _( `! s  h  B0 p
  变量:wrk
7 v: g) z1 x# ^. j, z' V! D3 y, R$ U+ h8 u: V
复制代码
, c% _- z1 |1 }% Bwrk = {# w1 j) k1 O$ M+ }' g  O5 C4 C
    scheme  = "http",
) Y' z( r  _' F7 }1 t4 v9 R- \    host    = "localhost",
5 w2 Z" M3 T' {2 Y0 u0 v    port    = nil,; B* {' C+ m9 r
    method  = "GET",! \1 _' Z( ~1 |/ u
    path    = "/",
, \4 w) ~: D9 y; c4 d    headers = {},
3 l. s% f+ `! Z. u    body    = nil,
4 Z2 k& Y- Q9 Y$ B" |6 Q    thread  = <userdata>,
% [: K. |3 W! J" {- q- v  }7 P0 L% M4 J9 A- C1 R' f. W0 g' k6 G
复制代码( `1 [5 g, n' [0 y* e8 @4 J

( z& w, V1 G7 o" m
9 V! L  U5 q) g2 Z* h6 E. s  方法:wrk.fomat wrk.lookup wrk.connect                  / [/ s* F1 c" Q& ?" A

" n! K" P8 p6 f8 Hfunction wrk.format(method, path, headers, body)  --根据参数和全局变量wrk,生成一个HTTP rquest string。
2 b6 ^9 q2 o, U. N- H3 j8 y, h  |function wrk.lookup(host, service)  --给定host和service(port/well known service name),返回所有可用的服务器地址信息。+ v5 o: {3 y6 K5 P3 z' P( S
function wrk.connect(addr)  --测试与给定的服务器地址信息是否可以成功创建连接
. C% @; q4 L( U  i' Q8 P; A  [
4 j0 V; `3 b5 h: v, {) N/ ^5 |( T% K1 h7 P' o) U, }
3、lua脚本压测实例
# X: \- B0 R! R% ~! r
, M+ s7 n% P- ~$ t" I  压测命令:wrk -t8 -c200 -d30s --latency  -s test.lua http://www.bing.com
; [+ c1 M) y3 o3 k7 X: e$ u" N
1 J/ f& B3 m9 }  test.lua是用lua写的压测脚本,如下是压测脚本的实例:
  d4 t% l8 g5 D1 `  L. x. F# g0 l6 t& b7 Q% U
  使用post方法压测
) t: \" \1 t8 |! G# H+ ~. N8 [( n* u% E8 a8 o' f- b  _
复制代码
  E! l, F! R8 k; ^wrk.method = "POST"* u4 A9 D1 g1 v3 T* D' e7 e; U
wrk.headers["S-COOKIE2"]="a=2&b=Input&c=10.0&d=20191114***"
+ e$ P( _( E2 U, O+ Nwrk.body = "recent_seven=20191127_32;20191128_111"
) J2 G3 Q7 p& R  Z: V( Bwrk.headers["Host"]="api.shouji.**.com". x. R$ o" c/ t) [, Y
" S- U# ^) t9 Y
function response(status,headers,body)
. f( T+ j% o. v. ]        if status ~= 200 then --将服务器返回状态码不是200的请求结果打印出来
) Y+ @$ T% ^* x' C$ M5 n                print(body)
8 z- r7 `0 b$ }% @        --      wrk.thread:stop()3 G% o+ f  _/ ]3 W
        end' h, u7 A9 b5 J- d0 y- {2 R5 A4 t
end
' _. N, @4 l0 {! G$ Y, z% n3 j/ Q复制代码6 A5 O# \8 Q* e; N
' J: k4 |. ?1 Q+ z+ E# l

/ W) ]$ G  }8 h: J2 `- c   发送json6 a6 l3 b1 u) z1 J1 q( D4 S

7 E: g8 d  w% s* H5 j复制代码2 M" P; Z  o# y8 C; i# E, p
request = function()! v' v% D3 O( z
    local headers = { }
" |7 ~: i' Z; i2 Y1 L. @7 L- A    headers['Content-Type'] = "application/json"
, x8 q- B# [6 d( Q% V    body = {* U1 U) n6 G+ J# h. y" y  r2 \
        mobile={"1533899828"},
! |4 ^# N& L5 U! o        params={code=math.random(1000,9999)}" {3 U% G9 D& n* N3 W: x/ ^  h
    }2 }. z) p; E5 o; C/ O+ z: S
    local cjson = require("cjson"), j$ D* A/ o9 A  e( h/ D
    body_str = cjson.encode(body)$ D4 E! T) f( o, B% c
    return wrk.format('POST', nil, headers, body_str)
  ~# i5 Z+ w: N6 N& m6 n- s9 |end
3 h0 a6 O4 m5 b+ Z& S: R复制代码1 P) C( p4 r- z1 q. {. ]

1 Z1 c' e/ [4 z( C7 A9 n/ ~" |9 |+ R2 ^% u
wrk读取文件,实现随机header-cookie
" N; k$ k  v: }4 Q* A1 F# x8 a1 m( s4 b8 x; B  H" x, H: g
复制代码
4 R: V+ e9 |9 e4 pidArr = {}
% n5 v1 d+ j1 k8 b" \* A" T8 i( r! Yfalg = 0
  p4 \, H! a$ xwrk.method = "POST"
" q# R) _$ x  E8 D" Z: _wrk.body = "a=1"
7 s) k' @/ w0 Bfunction init(args)
1 a  Q# J& X+ ?! b  R        for line in io.lines("integral/cookies.txt") do, ^/ A. g4 v4 A5 M* V0 v/ N
                print(line)
# \$ h' ]# e' M* I$ V4 X  f& C                idArr[falg] = line1 L! N+ z1 [2 e: F, D7 }
                falg = falg+1: o: w6 T0 w3 }, `
        end7 {" F  _; y0 M/ m8 |; m
        falg = 09 R* x- Q/ L% i# _/ v  t$ R
end+ ~2 C7 n4 \% z3 _0 f, ?% {: [

' Z& B" x, e' j--wrk.method = "POST"6 O9 _9 y- Z! Q1 E( ]" I
--wrk.body = "a=1"- n5 P, I8 N2 [" o6 p% {4 \. p# k
--wrk.path = "/v1/points/reading"
# {8 w$ f- b; `7 f
; C9 ^4 o$ t' K( _: ?request = function()
$ \) B  @1 B0 u* o& \3 s        parms = idArr[math.random(0,4)] --随机传递文件中的参数
8 g' B  B# S6 `' n( c' l; J        --parms = idArr[falg%(table.getn(idArr)+1)] 循环传递文件中的参数
$ U8 u: o7 G( K        wrk.headers["S-COOKIE2"] = parms: C- w$ H" ^- I7 O* @
        falg = falg+15 ~. M1 L2 F( {
        return wrk.format()/ V$ M0 d5 G# T
end9 N' {- o6 ~7 f
复制代码
# N0 v4 u/ g2 D$ a: J( r1 F
4 c4 U; Y) ]2 u) w( H9 J  k2 z! x" O3 z0 n3 t
  wrk创建数组并初始化,拼接随机参数$ ?# Y: f- P9 M) h( n

' o: X9 ^1 e) ~, {, s$ W复制代码
* E2 T" K1 ^* e6 U+ M( X( MidArr = {};
4 {! y0 Z8 J9 o3 ~5 h3 t% Nfunction init(args)
2 y, U7 a* F* x' g        idArr[1] = "1";& @6 h9 h6 h" z0 s( @
        idArr[2] = "2";
  s) f' L& h& Y! R6 {3 A4 @        idArr[3] = "3";
1 @3 T3 _8 d+ x) I) v        idArr[4] = "4";' i+ C; l; S2 t- b$ Z5 [( m' a3 ^
end
4 O& r0 h+ @8 @/ b  v  V# o
0 }. _9 P2 O3 Z3 h/ |request = function()
  |" J; N7 w4 N; ]1 J        parms = idArr[math.random(1,4)]) N1 O3 k+ K7 B
        path = "/v1/points/reading?id="..parms
2 @9 S' L. H5 c' R7 z" `        return wrk.format("GET",path)
/ d) H8 S$ q; |( v9 `9 b' E, b: X# Yend( n! o; N. k) M9 {8 V4 h
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 04:33 , Processed in 0.023973 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表