WRK-asyncflow框架性能压测
...大约 5 分钟
WRK-asyncflow框架性能压测
环境配置
- macOS、wrk 4.2.0
wrk-轻量级测试工具
1.wrk 安装与使用
wrk 是一款轻量级性能压测框架。
macos 安装配置wrk
# 检索wrk版本信息
brew search wrk
# 使用homebrew安装配置wrk
brew install wrk
# 安装验证(output:wrk 4.2.0 [kqueue] Copyright (C) 2012 Will Glozer)
wrk -v
wrk 使用
# 访问百度测试(命令说明:使用8个线程、200个并发、持续10s 压测百度连接)
wrk -t8 -c200 -d10s --latency "http://www.baidu.com"
# output
wrk -t8 -c200 -d10s --latency "http://www.baidu.com"
Running 10s test @ http://www.baidu.com
# part 01
8 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 294.17ms 381.59ms 1.95s 81.02%
Req/Sec 64.48 35.85 260.00 76.64%
# part 02
Latency Distribution
50% 83.33ms
75% 312.75ms
90% 746.66ms
99% 1.59s
# part 03
5141 requests in 10.07s, 52.66MB read
Socket errors: connect 0, read 5, write 0, timeout 111
Requests/sec: 510.47
Transfer/sec: 5.23MB
响应参数解读(参考上述结果示例,拆分3部分进行解读)
part 01
- 表参数解读:Avg(平均值)、Max(最大值)、Stdev(标准差:表示统计数据的离散程度,标准差太大表示响应波动比较大)
- Latency(延迟):Avg(平均延迟)=》294.17ms、Max(最大延迟)=》1.95s
- 可以看出响应时间有不少波动,属于正常现象,一般最大延迟在1s内还属于可接受的范畴,可结合响应参数思考优化方案
- Req/Sec:Avg(平均值)=》64.48/s、Max(最大值)=》260/s、Stdev(标准差)
- Latency(延迟):Avg(平均延迟)=》294.17ms、Max(最大延迟)=》1.95s
- 表参数解读:Avg(平均值)、Max(最大值)、Stdev(标准差:表示统计数据的离散程度,标准差太大表示响应波动比较大)
part 02(不同分位延迟数据)
- Latency Distribution:不同分位的延迟(可理解为按响应时间从小到大排序,排在某个百分比位置的数据):比如一共1000个请求,那么响应时间排名第990个请求的响应时间就是99%分位数值,对应到上述结果即99%的请求都在1.59s以内,只有1%的请求是在1.59以上。这些数值其实相对于平均值可以提供更多参考
part 03(总结性数据)
- 表示10s内发送了5141个请求,错误了0个(一般如果出现错误数errors都要进行重测,否则再快也没用)
- Requests/sec:510.47(QPS为510.47/s):此处对比part 01部分的Req/Sec(Avg),此处是其8倍左右(正好是开启线程的数量),因此part01部分的Req/Sec是单个线程的数据
2.使用lua脚本进行压测接口请求
wrk 工具嵌入了lua脚本语言,在自定义压测场景时,可以在wrk目录下使用lua定制压测场景
lua 声明周期
lua 声明周期 共有3个阶段:启动阶段、运行阶段、结束阶段,wrk 支持在这3个阶段对压测进行个性化
启动阶段
function setup(thread)
在脚本文件中实现setup方法,wrk就会在测试线程已经初始化但还没有启动的时候调用该方法。wrk会为每一个测试线程调用一次setup方法,并传入代表测试线程的对象thread作为参数。setup方法中可操作该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() --在每次发送request之前调用,如果需要delay,那么delay相应时间;
function request() --用来生成请求;每一次请求都会调用该方法,所以注意不要在该方法中做耗时的操作;
function response(status, headers, body) --在每次收到一个响应时调用;为提升性能,如果没有定义该方法,那么wrk不会解析headers和body;
结束阶段
function done(summary, latency, requests) --在整个测试过程中只会调用一次,可从参数给定的对象中,获取压测结果,生成定制化的测试报告。
自定义脚本中可访问的变量和方法
变量:wrk
wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = <userdata>,
}
方法:wrk.format、wrk.lookup、wrk.connect
function wrk.format(method, path, headers, body) --根据参数和全局变量wrk,生成一个HTTP rquest string。
function wrk.lookup(host, service) --给定host和service(port/well known service name),返回所有可用的服务器地址信息。
function wrk.connect(addr) --测试与给定的服务器地址信息是否可以成功创建连接
lua 脚本压测实例
压测命令:wrk -t8 -c200 -d30s --latency -s xxxx.lua https://www.baidu.com
(基于lua脚本,使用8个线程模拟200个并发,持续20s压测指定url)
基于springboot-demo-druid项目,构建接口模拟压测,可借助日志和输出确认接口压测是否正常
GET 请求
// 普通GET请求
@GetMapping("/getName")
public String getName(@RequestParam String name) {
System.out.println(name);
return name;
}
# 默认参数压测命令
wrk -t8 -c200 -d5s --latency "http://127.0.0.1:8080/api/demo/getName?name=xxx"
# lua脚本:showName.lua
nameArr = {};
function init(args)
nameArr[1] = "Alice";
nameArr[2] = "Bob";
nameArr[3] = "Juice";
nameArr[4] = "David";
nameArr[5] = "Jason";
end
request = function()
parms = nameArr[math.random(1,5)]
path = "http://127.0.0.1:8080/api/demo/getName?name="..parms
return wrk.format("GET",path)
end
function response(status,headers,body)
if status ~= 200 then -- 将服务器返回状态码不是200的请求结果打印出来
print(body)
-- wrk.thread:stop()
end
end
# 压测指令(注意lua脚本中的path指定)
wrk -t8 -c200 -d5s --latency -s getName.lua "http://127.0.0.1:8080/api"
POST 请求
// 普通POST请求
@PostMapping("/showInfo")
public String showInfo(@RequestHeader HttpHeaders headers,@RequestParam String name,@RequestParam int age) {
System.out.println(headers.get("USER_TOKEN"));
System.out.println(headers.get("Host"));
System.out.println("name:"+name+",age:"+age);
return name;
}
// showInfo.lua
wrk.method = "POST"
wrk.headers["USER_TOKEN"]="ABCDEFG"
wrk.body = "name=Alice&age=18"
wrk.headers["Host"]="localhost"
wrk.headers["Content-Type"]="application/x-www-form-urlencoded"
function response(status,headers,body)
if status ~= 200 then --将服务器返回状态码不是200的请求结果打印出来
print(body)
-- wrk.thread:stop()
end
end
# 压测命令
wrk -t8 -c200 -d5s --latency -s showInfo.lua "http://127.0.0.1:8080/api/demo/showInfo"
// POST请求(JSON数据)
@PostMapping("/showJson")
public String showJson(@RequestHeader(name = "USER_TOKEN") String userToken,@RequestHeader(name = "Host") String host,@RequestBody JSONObject jsonObject) {
String res = jsonObject.toJSONString();
System.out.println("userToken:"+userToken+",host:"+host+",res:"+res);
return res;
}
# showJson.lua
wrk.method = "POST"
wrk.headers["USER_TOKEN"]="ABCDEFG"
wrk.body = "{\"name\":\"Jason\",\"age\":18}"
-- wrk.body = "{}"
wrk.headers["Host"]="localhost"
wrk.headers["Content-Type"]="application/json"
function response(status,headers,body)
if status ~= 200 then --将服务器返回状态码不是200的请求结果打印出来
print(body)
-- wrk.thread:stop()
end
end
# 压测命令
wrk -t8 -c200 -d5s --latency -s showJson.lua "http://127.0.0.1:8080/api/demo/showJson"
任务插入场景压力测试(wrk)
# wrk 性能压测:8个线程、50个并发、持续10s =》压测任务创建接口
wrk -t8 -c50 -d10s --latency "http://localhost:8080/api/task/create"
# 脚本测试
wrk -t8 -c50 -d10s --script=create_task.lua --latency "http://localhost:8080/api/task/create"
Powered by Waline v3.1.3