立即注册 登录
About云-梭伦科技 返回首页

pig2的个人空间 https://www.aboutyun.com/?61 [收藏] [复制] [分享] [RSS]

日志

QPS性能测试工具WRK的简明教程

已有 1137 次阅读2020-12-14 16:31 |系统分类:大数据

一、wrk介绍
wrk 是一款针对 Http 协议的基准测试工具,它能够在单机多核 CPU 的条件下,使用系统自带的高性能 I/O 机制,如 epoll,kqueue 等,通过多线程和事件模式,对目标机器产生大量的负载。

二、 wrk 的优势与劣势
1、优势:
轻量级性能测试工具;
安装简单(相对 Apache ab 来说);
学习曲线基本为零,几分钟就能学会咋用了;
基于系统自带的高性能 I/O 机制,如 epoll, kqueue, 利用异步的事件驱动框架,通过很少的线程就可以压出很大的并发量;
2、劣势:
wrk 目前仅支持单机压测,后续也不太可能支持多机器对目标机压测,因为它本身的定位,并不是用来取代 JMeter, LoadRunner 等专业的测试工具,wrk 提供的功能,对我们后端开发人员来说,应付日常接口性能验证还是比较友好的。

三、wrk 安装
wrk 只能被安装在类 Unix 系统上,所以我们需要一个 Linux 或者 MacOS 环境。

1、Ubuntu/Debian
依次执行如下命令:

sudo apt-get install build-essential libssl-dev -y

git clone https://github.com/wg/wrk.git wrk

cd wrk;make

sudo cp wrk /usr/local/bin

2、CentOS / RedHat / Fedora
依次执行如下命令:

sudo yum groupinstall 'Development Tools'

sudo yum install -y openssl-devel

git clone https://github.com/wg/wrk.git wrk

cd wrk;make

sudo cp wrk /usr/local/bin

3、MacOS 安装
Mac 系统也可以通过源码编译安装,但是更推荐使用 brew 的方式来安装:

brew install wrk

四、使用步骤
1、简单使用
wrk -t12 -c400 -d30s http://www.baidu.com

这条命令表示,利用 wrk 对 www.baidu.com 发起压力测试,线程数为 12,模拟 400 个并发请求,持续 30 秒。

2、wrk 子命令参数说明
除了上面简单示例中使用到的子命令参数,wrk 还有其他更丰富的功能,命令行中输入 wrk --help, 可以看到支持以下子命令:

使用方法: wrk <选项> <被测HTTP服务的URL>
Options:                                           
     -c, --connections <N>     跟服务器建立并保持的TCP连接数量 
     -d, --duration       <T>      压测时间          
     -t, --threads         <N>      使用多少个线程进行压测                                                        
     -s, --script            <S>      指定Lua脚本路径      
     -H, --header         <H>     为每一个HTTP请求添加HTTP头     
           --latency                     在压测结束后,打印延迟统计信息  
           --timeout         <T>      超时时间    
     -v, --version                       打印正在使用的wrk的详细版本信息

注:

<N>代表数字参数,支持国际单位 (k, M, G)

<T>代表时间参数,支持时间单位 (s, m, h)

关于线程数不是设置的越大,压测效果越好,一般来说,推荐设置成压测机器 CPU 核心数的 2 倍到 4 倍就行了。线程设置过大会导致线程切换过于频繁,效果降低,

3、测试报告
执行压测命令:

wrk -t12 -c400 -d30s --latency http://www.baidu.com

执行上面的压测命令,30 秒压测过后,生成如下压测报告:

Running 30s test @ http://www.baidu.com (压测时间30s)
   12 threads and 400 connections (共12个测试线程,400个连接)
   Thread Stats   Avg(平均值)     Stdev(标准差)           Max(最大值)         +/- Stdev(正负一个标准差所占比例)
     Latency         386.32ms         380.75ms                 2.00s                     86.66%
     Req/Sec        17.06                13.91                       252.00                   87.89%
   Latency Distribution (延迟分布)
      50%  218.31ms
      75%  520.60ms
      90%  955.08ms
      99%    1.93s
   4922 requests in 30.06s, 73.86MB read (30.06s内处理了4922个请求,耗费流量73.86MB)
   Socket errors: connect 0, read 0, write 0, timeout 311 (错误统计)
Requests/sec:    163.76 (QPS 163.76,即平均每秒处理请求数为163.76)
Transfer/sec:      2.46MB (平均每秒流量2.46MB)

注:

标准差,简单来说,标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大;一个较小的标准差,代表这些数值较接近平均值。标准差如果太大说明样本本身离散程度比较高,有可能系统性能波动较大。

4、使用 Lua 脚本进行复杂测试
如果我想进行 POST 请求,而且每次的请求参数都不一样,用来模拟用户使用的实际场景,怎么测试?

对于这种需求,我们可以通过编写 Lua 脚本的方式,在运行压测命令时,通过参数 --script 来指定 Lua 脚本,来满足个性化需求。

1)wrk 对 Lua 脚本的支持
wrk 支持在三个阶段对压测进行个性化,分别是启动阶段、运行阶段和结束阶段。每个测试线程,都拥有独立的Lua 运行环境。

启动阶段:

function setup(thread)

在脚本文件中实现 setup 方法,wrk 就会在测试线程初始化后,但还没有启动的时候调用该方法。wrk会为每一个测试线程调用一次 setup 方法,并传入代表测试线程的对象 thread 作为参数。setup 方法中可操作该 thread 对象,用于获取信息、存储信息、甚至关闭该线程。thread可做如下操作:

thread.addr - get or set the thread's server address thread:get(name) - get the value of a global in the thread's env thread:set(name, value) - set the value of a global in the thread's env thread:stop() - stop the thread

运行阶段:

function init(args)

由测试线程调用,只会在进入运行阶段时,调用一次。支持从启动 wrk 的命令中,获取命令行参数。

function delay()

在每次发送请求之前调用,如果需要定制延迟时间,可以在这个方法中设置。

function request()

用来生成请求, 每一次请求都会调用该方法,注意不要在该方法中做耗时的操作。

function response(status, headers, body)

在每次收到一个响应时被调用,为提升性能,如果没有定义该方法,那么wrk不会解析 headers 和 body;

结束阶段:

function done(summary, latency, requests)

在整个测试过程中只会被调用一次,我们可以从给定的参数中,获取压测结果,生成定制化的测试报告。

自定义 Lua 脚本中可访问的变量以及方法:

变量wrk定义了一个 table 类型的全局变量,修改该 wrk 变量,会影响所有请求。

wrk = {
     scheme  = "http",
     host    = "localhost",
     port    = 8080,
     method  = "GET",
     path    = "/",
     headers = {},
     body    = nil,
     thread  = <userdata>,
   }

方法:

function wrk.format(method, path, headers, body)

wrk.format returns a HTTP request string containing the passed parameters merged with values from the wrk table.

根据参数和全局变量 wrk,生成一个 HTTP rquest 字符串。

function wrk.lookup(host, service)

wrk.lookup returns a table containing all known addresses for the host and service pair. This corresponds to the POSIX getaddrinfo() function.

给定 host 和 service(port/well known service name),返回所有可用的服务器地址信息。

function wrk.connect(addr)

wrk.connect returns true if the address can be connected to, otherwise it returns false. The address must be one returned from wrk.lookup().

测试给定的服务器地址信息是否可以成功创建连接

2)通过 Lua 脚本压测示例
调用 POST 接口:

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

注意: wrk 是个全局变量,这里对其做了修改,使得所有请求都使用 POST 的方式,并指定了 body 和 Content-Type头。

自定义每次请求的参数:

request = function()
    uid = math.random(1, 10000000)
    path = "/test?uid=" .. uid
    return wrk.format(nil, path)
end

在 request 方法中,随机生成 1~10000000 之间的 uid,并动态生成请求 URL.

每次请求前,延迟 10ms:

function delay()
    return 10
end

请求的接口需要先进行认证,获取 token 后,才能发起请求的处理方法:
token = nil
path  = "/auth"

request = function()
    return wrk.format("GET", path)
end

response = function(status, headers, body)
    if not token and status == 200 then
       token = headers["X-Token"]
       path  = "/test"
       wrk.headers["X-Token"] = token
    end
end

上面的脚本表示,在 token 为空的情况下,先请求 /auth 接口来认证,获取 token, 拿到 token 以后,将 token 放置到请求头中,再请求真正需要压测的 /test 接口。

压测支持 HTTP pipeline 的服务:

init = function(args)
    local r = {}
    r[1] = wrk.format(nil, "/?foo")
    r[2] = wrk.format(nil, "/?bar")
    r[3] = wrk.format(nil, "/?baz")

   req = table.concat(r)
end

request = function()
    return req
end

通过在 init 方法中将三个 HTTP请求拼接在一起,实现每次发送三个请求,以使用 HTTP pipeline。

原文链接
https://www.cnblogs.com/realjimmy/p/13458482.html

路过

雷人

握手

鲜花

鸡蛋

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 立即注册

关闭

推荐上一条 /2 下一条