共计 4974 个字符,预计需要花费 13 分钟才能阅读完成。
原文连贯:https://blog.fengjx.com/wrk/
wrk 是一个相似 ab(apache bench)、jmeter 的压力测试工具,底层基于 epoll 和 kqueue 实现,能充分利用服务器 cpu 资源,升高测试工具自身性能开销对测试后果准确性的影响。反对应用 lua 脚本自定义测试逻辑,应用上非常简单,但性能足够弱小。
没有理解过 lua 的同学,能够看下 lua 扼要教程 https://coolshell.cn/articles…
装置
- linux https://github.com/wg/wrk/wik…
- macOS https://github.com/wg/wrk/wik…
- windows(Windows Subsystem for Linux) https://github.com/wg/wrk/wik…
用法
$ wrk -h
wrk: invalid option -- h
Usage: wrk <options> <url>
Options:
-c, --connections <N> Connections to keep open
-d, --duration <T> Duration of test
-t, --threads <N> Number of threads to use
-s, --script <S> Load Lua script file
-H, --header <H> Add header to request
--latency Print latency statistics
--timeout <T> Socket/request timeout
-v, --version Print version details
参数 | 阐明 |
---|---|
-c | 与服务器放弃的 http 连接数 |
-d | 压测工夫 |
-t | 应用线程数 |
-s | 自定义 lua 脚本门路 |
-H | 自定义 http header 申请头,例如:”User-Agent: benchmark-wrk” |
–latency | 打印提早统计数据 |
–timeout | http 超时工夫 |
–version | 打印版本信息 |
eg: wrk -t2 -c5 -d10s https://httpbin.org/get
这种状况只实用于每个申请都雷同的状况
$ wrk -t2 -c5 -d10s https://httpbin.org/get
Running 10s test @ https://httpbin.org/get
2 threads and 5 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 251.97ms 50.38ms 510.96ms 94.52%
Req/Sec 7.60 2.40 10.00 75.23%
146 requests in 10.05s, 61.17KB read
Requests/sec: 14.52
Transfer/sec: 6.08KB
编写 lua 测试脚本
官网文档:https://github.com/wg/wrk/blo…
编写 lua 脚本能够实现简单的测试场景,例如:须要登录认证的接口,查问不必 id 的数据(雷同 id 服务端可能有缓存,达不到实在压测成果)
先看官网一个简略的自定义脚本
wrk.method = "POST"
wrk.body = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
$ wrk -d3s -c2 -s scripts/post.lua https://httpbin.org/get
wrk 是一个内置的全局 table 类型变量,不须要定义能够间接应用,批改 wrk 变量的值,会对所有申请都失效。
wrk = {
scheme = "http",
host = "localhost",
port = nil,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = <userdata>
}
wrk 内置函数
- wrk.format
function wrk.format(method, path, headers, body)
wrk.format returns a HTTP request string containing the passed parameters
merged with values from the wrk table.返回一个 http 申请字符串,参数会笼罩 wrk 全局配置,能够通过 format 能够结构出不同的 request
- wrk.lookup
function wrk.lookup(host, service)
wrk.lookup returns a table containing all known addresses for the host
and service pair. This corresponds to the POSIX getaddrinfo() function.返回所有可用服务器的地址信息
-
wrk.connect
function wrk.connect(addr)
wrk.connect returns true if the address can be connected to, otherwise
it returns false. The address must be one returned from wrk.lookup().测试指定的服务器地址是否能失常连贯
参考:
local addrs = nil function setup(thread) if not addrs then addrs = wrk.lookup(wrk.host, wrk.port or "http") for i = #addrs, 1, -1 do if not wrk.connect(addrs[i]) then table.remove(addrs, i) end end end thread.addr = addrs[math.random(#addrs)] end function init(args) local msg = "thread addr: %s" print(msg:format(wrk.thread.addr)) end
生命周期回调函数
wrk 包含上面几个生命周期,在脚本中从新定义这些全局函数,能够批改 wrk 默认行为,实现个性化测试需要。
The following globals are optional, and if defined must be functions:
global setup -- called during thread setup
global init -- called when the thread is starting,global delay -- called to get the request delay,global request -- called to generate the HTTP request,global response -- called with HTTP response data,global done -- called with results of run
启动阶段
-
setup 每个线程初始化时执行一次
function setup(thread)
setup 办法会传入一个 thread 对象,能够批改或设置 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,终止线程
执行阶段
-
init 每个线程开始启动时执行一次
function init(args)
args 是通过命令行传入的参数,通过
--
指定例如:
wrk -d3s -c2 -s wrk.lua https://httpbin.org/get -- test 100
function init(args) for i, v in ipairs(args) do print(i,v) end end -- 输入 -- 1 test -- 2 100
- delay 每次发送申请时,间隔时间(ms),每次申请执行一次
function delay()
返回值决定每个申请距离
- request 创立 request 时(发送 request 前)执行,每次申请执行一次
function request()
个别在这里会配合
wrk.format
办法,动态创建申请,这里不要执行耗时的代码,否则会影响测试后果准确性 - response http 响应时执行,每次申请执行一次
function response(status, headers, body)
http 响应解决逻辑,参数对应 http 响应的
status
,headers
,body
。解析 header 和 body 的开销比拟大,所以如果没有定义
response
回调办法的话,wrk 就不会解析 header 和 body,这样测试后果会更加精确(解析响应数据是客户端负责的,不能算到服务器解决工夫外面)
完结阶段
-
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 } }
官网示例
https://github.com/wg/wrk/blo…
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
更多用法查看官网示例:https://github.com/wg/wrk/tre…