wrk压测工具使用

介绍分为四部分

  1.wrk简述

  2.wrk安装

  3.wrk运行参数

  4.wrk高级用法

1.wrk简述

当使用ab做压测的时候发现,ab的客户端消耗很大,而且测试时性能较差,测试redis,spring boot时性能都与官方介绍相差太多,由此引入wrk.

wrk是一款简单的HTTP压测工具,托管在Github上, https://github.com/wg/wrk.
wrk 的一个很好的特性就是能用很少的线程压出很大的并发量. 原因是它使用了一些操作系统特定的高性能 io 机制, 比如 select, epoll, kqueue 等. 其实它是复用了 redis 的 ae 异步事件驱动框架. 确切的说 ae 事件驱动框架并不是 redis 发明的, 它来至于 Tcl的解释器 jim, 这个小巧高效的框架, 因为被 redis 采用而更多的被大家所熟知.
wrk源码涉及到很多系统内核的调用,指望另有大神阅读并出示解释,引用一篇:https://blog.csdn.net/codingwithme/article/details/52251451

2.wrk安装

在mac上可以使用brew安装:

brew install wrk

也可以使用源码安装:

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

3.wrk运行参数

wrk常规操作:

wrk -t15 -c300 -d10 --latency -s generateIDCode.lua http://localhost:14077/test

-t : thread 开启线程数

-c : connection 服务端连接数

-d : during 测试时间

—latency : 显示时延分布

结果如下:

Running 10s test @ http://10.1.4.55:14077/test
  15 threads and 300 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.89ms   12.65ms 244.40ms   98.05%
    Req/Sec     4.40k     0.86k    6.15k    82.42%
  Latency Distribution
     50%    3.88ms
     75%    5.59ms
     90%    8.28ms
     99%   31.96ms
  657863 requests in 10.10s, 53.33MB read
Requests/sec:  65137.56
Transfer/sec:      5.28MB

这里面比较复杂的是lua脚本的编写,正常http,post访问需要提供一份lua脚本:

wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"
wrk.body = '{"header": {"requestTime": "2018100910320000","requestSeq": "e379853d-d93e-4249-b9be-8a272b","appId": "bc1f4a2a995b47db9018031801984857"},"content": {"duration": "300","idCard": "350123199502150000sfsdafwjdhsjofwofnsdfnjdwfnew1561651dsfsdnklndsjfn1165165165fdsfhweufwehfjdsnfiefenf350123199502150000sfsdafwjdhsjofwofnsdfnjdwfnew1561651dsfsdnklndsjfn1165165165fdsfhweufwehfjdsnfiefenf350123199502150000","expressParam": "expressParamexpressParaexpres","name": "name","isPic": "0","availableTimes": "5"}}'

到这里就满足大多数情况的压测使用了.只不过我们习惯性拓展一下:

这里要记录wrk用这种方式提供了哪些可自定义的东西

变量值:

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

方法:

-- 生成整个request的string,例如:返回
-- GET / HTTP/1.1
-- Host: tool.lu
function wrk.format(method, path, headers, body)

-- 获取域名的IP和端口,返回table,例如:返回 `{127.0.0.1:80}`
function wrk.lookup(host, service)

-- 判断addr是否能连接,例如:`127.0.0.1:80`,返回 truefalse
function wrk.connect(addr)


function setup(thread)

-- thread提供了1个属性,3个方法
-- thread.addr 设置请求需要打到的ip
-- thread:get(name) 获取线程全局变量
-- thread:set(name, value) 设置线程全局变量
-- thread:stop() 终止线程

function init(args)
-- 每个线程仅调用1次,args 用于获取命令行中传入的参数, 例如 --env=pre

function delay()
-- 每个线程调用多次,发送下一个请求之前的延迟, 单位为ms

function request()
-- 每个线程调用多次,返回http请求

function response(status, headers, body)
-- 每个线程调用多次,返回http响应

function done(summary, latency, requests)


latency.min              -- minimum value seen
latency.max              -- maximum value seen
latency.mean             -- average value seen
latency.stdev            -- standard deviation
latency:percentile(99.0) -- 99th percentile value
latency(i)               -- raw value and count

summary = {
  duration = N,  -- run duration in microseconds
  requests = N,  -- total completed requests
  bytes    = N,  -- total bytes received
  errors   = {
    connect = N, -- total socket connection errors
    read    = N, -- total socket read errors
    write   = N, -- total socket write errors
    status  = N, -- total HTTP status codes > 399
    timeout = N  -- total request timeouts
  }
}

4.wrk高级用法

两个例子:例子是网上找的,但是这两个功能是最实用的,其他方法变量用到的场景都比较少:

1.请求时,打印response内容:

function response(status, headers, body)
      print(body)
end

2.请求时,构造变动的随机id:

request = function()
    counter = counter + 1
    local task_id = string.format("%d-%s", os.time()*10000+math.random(1, 10000), randomString(10))
 
    local data = [[{
        "task_timeout": 30,
        "task_id": "%s",
        "task_body": {
            "url_list": [
            {
                "subtask_id": "1000000022511092",
                "url": "http://zhihu.com/upic/2017/08/24/15/kk.webp",
                "force": true
            },
            {
                "subtask_id": "1000000022511093",
                "url": "http://zhihu.com/upic/2017/08/24/15/zz.jpg",
                "force": true
            }
            ]
        },
        "ip_list": [],
        "ip_list_flag": false,
        "task_type": "refresh",
        "retry_failed": false,
        "working_layer": "polymerization"
    }]]
 
    wrk.method = "POST"
    wrk.body   = string.format(data, tostring(task_id))
    wrk.headers["Content-Type"] = "application/json"
    -- return wrk.format("POST", "/v1/engine/task")
    return wrk.format()
 
end

 以及:

local queries = {
    "language=php",
    "language=java",
    "language=lua"
}
local i = 0
request = function()
    local body = wrk.format(nil, nil, nil, queries[i % #queries + 1])
    i = i + 1
    return body
end

 

 

原文地址:https://www.cnblogs.com/garfieldcgf/p/10002698.html