压测工具使用教程
1.wrk使用教程
1.1 安装
#安装依赖
yum -y install gcc
#上传wrk源码包或者,安装git后从github拉取源码,建议前者
rz wrk-4.1.0.zip
#进入源码包目录,执行make
make
#将make后的wrk文件复制到/usr/bin目录下
cp wrk /usr/bin
1.2 简单使用
#执行命令进行测试
wrk -t8 -c20 -d10s http://www.baidu.com
#展示如下结果说明成功
[root@localhost home]# wrk -t2 -c20 -d10s http://www.baidu.com
Running 10s test @ http://www.baidu.com
2 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 31.28ms 13.58ms 353.07ms 91.47%
Req/Sec 323.49 31.45 386.00 72.00%
6458 requests in 10.03s, 96.10MB read
Socket errors: connect 0, read 28, write 0, timeout 0
Requests/sec: 644.11
Transfer/sec: 9.59MB
一般线程数不宜过多. 核数的2到4倍足够了. 多了反而因为线程切换过多造成效率降低. 因为 wrk 不是使用每个连接一个线程的模型, 而是通过异步网络 io 提升并发量. 所以网络通信不会阻塞线程执行. 这也是 wrk 可以用很少的线程模拟大量网路连接的原因. 而现在很多性能工具并没有采用这种方式, 而是采用提高线程数来实现高并发. 所以并发量一旦设的很高, 测试机自身压力就很大. 测试效果反而下降.
参数解释:
-
2个线程,20个链接(不是一个线程对应一个连接)
-
latency 和 req/sec
代表单个线程的统计数据,
latency
代表延迟时间,Req/Sec
代表单个线程每秒完成的请求数,他们都具有平均值, 标准偏差, 最大值, 正负一个标准差占比。一般我们来说我们主要关注平均值和最大值. 标准差如果太大说明样本本身离散程度比较高. 有可能系统性能波动很大. -
6458 requests in 10.03s, 96.10MB read
10s内总共有6485个请求,总共读取96.10MB的数据
-
Socket errors: connect 0, read 28, write 0, timeout 0
总共有28个读错误,
-
Requests/sec和Transfer/sec
所有线程平均每秒钟完成644个请求,每秒钟读取9.59MB的数据。
如果想看看响应时间的分布,可以增加--latency
:
wrk -t2 -c20 -d10s --latency http://www.baidu.com
#结果为:
[root@localhost home]# wrk -t2 -c20 -d10s --latency http://www.baidu.com
Running 10s test @ http://www.baidu.com
2 threads and 20 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 27.32ms 9.05ms 207.10ms 93.65%
Req/Sec 368.52 25.84 424.00 81.00%
Latency Distribution
50% 25.65ms
75% 26.77ms
90% 28.62ms
99% 52.80ms
7361 requests in 10.03s, 109.55MB read
Socket errors: connect 0, read 28, write 0, timeout 0
Requests/sec: 733.86
Transfer/sec: 10.92MB
1.3 高级使用
wrk可以结合lua来做,通过wrk提供的几个lua函数来对请求进行修改,结果输出、设置延迟等操作。下面来看看wrk提供的几个lua函数:
-
setup 函数
这个函数在目标 IP 地址已经解析完, 并且所有 thread 已经生成, 但是还没有开始时被调用. 每个线程执行一次这个函数.
可以通过thread:get(name), thread:set(name, value)设置线程级别的变量. -
init 函数
每次请求发送之前被调用.
可以接受 wrk 命令行的额外参数. 通过 – 指定. -
delay函数
这个函数返回一个数值, 在这次请求执行完以后延迟多长时间执行下一个请求. 可以对应 thinking time 的场景.
-
request函数
通过这个函数可以每次请求之前修改本次请求的属性. 返回一个字符串. 这个函数要慎用, 会影响测试端性能.
-
response函数
每次请求返回以后被调用. 可以根据响应内容做特殊处理, 比如遇到特殊响应停止执行测试, 或输出到控制台等等.
function response(status, headers, body) if status ~= 200 then print(body) wrk.thread:stop() end end
-
done函数
在所有请求执行完以后调用, 一般用于自定义统计结果.
done = function(summary, latency, requests) io.write("------------------------------\n") for _, p in pairs({ 50, 90, 99, 99.999 }) do n = latency:percentile(p) io.write(string.format("%g%%,%d\n", p, n)) end end
官网示例:
-- example script that demonstrates use of setup() to pass
-- data to and from the threads
local counter = 1
local threads = {}
function setup(thread)
thread:set("id", counter)
table.insert(threads, thread)
counter = counter + 1
end
function init(args)
requests = 0
responses = 0
local msg = "thread %d created"
print(msg:format(id))
end
function request()
requests = requests + 1
return wrk.request()
end
function response(status, headers, body)
responses = responses + 1
end
function done(summary, latency, requests)
for index, thread in ipairs(threads) do
local id = thread:get("id")
local requests = thread:get("requests")
local responses = thread:get("responses")
local msg = "thread %d made %d requests and got %d responses"
print(msg:format(id, requests, responses))
end
end
1.3.1 GET带随机数请求
wrk.method = "GET"
wrk.body = ""
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
request = function()
idcard =tostring( math.random(1, 10000000000000))
path = "/hsxxdj-service/p/core/yidd/addPerson?name=zs&sex=%E7%94%B7&linkPhone=15837174664&idcard=400001A" .. idcard
return wrk.format(nil, path)
end
-- 调用方法
./wrk -t8 -c10000 -d10s --latency -s 脚本名称路径 http://36.137.253.3:9100
1.3.2 POST带随机参数请求
-- 可参考get进行处理,另外,如果需要增加token都可以通过request方法进行修改和扩展