跳至主要內容

WRK-asyncflow框架性能压测

holic-x...大约 5 分钟asyncflowasyncflow

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(标准差)
  • 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定制压测场景

wrk 使用lua脚本进行压测 官方示例open in new window

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