1. 使用wrk做测试
1. 下载源码,编译安装
[root@opinion-96 wrk]# git clone https://gitee.com/why168/wrk.git
[root@opinion-96 wrk]# cd wrk/ && make
2. 准备要压测的接口和lua脚本
1. 接口 https://ops.cninfo.com.cn/opinions/pageQuery
2. post.lua 脚本
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json;charset=UTF-8"
wrk.body = "{\"stockCode\":\"000004\",\"pageNo\":1,\"pageSize\":10,\"keywords\":[],\"titles\":[],\"keyword\":\"\",\"startDate\":\"2021-07-27T01:04:33.204Z\",\"endDate\":\"2022-01-27T01:04:33.204Z\",\"industry\":\"\",\"customKeyword\":[],\"date\":[\"2021-07-27T01:04:33.204Z\",\"2022-01-27T01:04:33.204Z\"]}"
3. 执行测试
./wrk -t4 -c200 -d60s -T5s --script=post.lua --latency https://ops.cninfo.com.cn/opinions/pageQuery
参数说明:
-c, --connections: total number of HTTP connections to keep open with
each thread handling N = connections/threads
-d, --duration: duration of the test, e.g. 2s, 2m, 2h
-t, --threads: total number of threads to use
-s, --script: LuaJIT script, see SCRIPTING
-H, --header: HTTP header to add to request, e.g. "User-Agent: wrk"
--latency: print detailed latency statistics
--timeout: record a timeout if a response is not received within
this amount of time.
4. 测试结果说明
[root@opinion-96 wrk]# ./wrk -t4 -c200 -d60s -T5s --script=post.lua --latency https://ops.cninfo.com.cn/opinions/pageQuery
Running 1m test @ https://ops.cninfo.com.cn/opinions/pageQuery
4 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 596.64ms 656.91ms 4.92s 86.22%
Req/Sec 114.67 39.57 262.00 70.26%
Latency Distribution
50% 420.30ms
75% 871.40ms
90% 1.47s
99% 2.95s
26926 requests in 1.00m, 281.58MB read
Socket errors: connect 0, read 0, write 0, timeout 6
Non-2xx or 3xx responses: 5
Requests/sec: 448.29
Transfer/sec: 4.69MB
5. 此时查看压测机
6. 当压测参数调整为 -t4 -c4 -d15m -T5s时,dstat监控显示如下:
推测应该是压测机的网卡,影响限制了压测结果
2. wrk中的lua脚本
wrk是一款现代化的http压测工具,提供lua脚本的功能可以满足每个请求或部分请求的差异化。
wrk中执行http请求的时候,调用lua分为3个阶段,setup,running,done,每个wrk线程中都有独立的脚本环境。
wrk的全局属性
wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = <userdata>,
}
wrk的全局方法
-- 生成整个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`,返回 true 或 false
function wrk.connect(addr)
Setup阶段
setup是在线程创建之后,启动之前。
function setup(thread)
-- thread提供了1个属性,3个方法
-- thread.addr 设置请求需要打到的ip
-- thread:get(name) 获取线程全局变量
-- thread:set(name, value) 设置线程全局变量
-- thread:stop() 终止线程
Running阶段
function init(args)
-- 每个线程仅调用1次,args 用于获取命令行中传入的参数, 例如 --env=pre
function delay()
-- 每个线程调用多次,发送下一个请求之前的延迟, 单位为ms
function request()
-- 每个线程调用多次,返回http请求
function response(status, headers, body)
-- 每个线程调用多次,返回http响应
Done阶段
可以用于自定义结果报表,整个过程中只执行一次
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
}
}
表单的提交
wrk.method = "POST"
wrk.body = "" -- 直接写死,如果不需要请求数据的差异化
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
-- 如果要实现每次都不一样的表单内容
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