WRK的全称是“Windows Research Kernel”,它是微软为高校操作系统课程提供的可修改和跟踪的操作系统教学平台。它给出了Windows这个成功的商业操作系统的内核大部分代码,可以对其进行修改、编译,并且可以用这个内核启动Windows操作系统。可让学生将操作系统基本原理和商业操作系统内核联系起来,进一步加深对操作系统整体的理解。
微软的WRK计划(Windows Research Kernel),这个计划是让高校师生以及亲密的合作商有一个机会能够了解和学习windows的内核代码。WRK包含了以下模块:
RUN apt-get update
RUN apt-get install git -y
RUN git clone https://github.com/wg/wrk.git
COPY wrk /app/
RUN apt-get -y install gcc automake autoconf libtool make libssl-dev
COPY target/classes/wrk /app/
RUN cd /app/wrk
RUN make
COPY wrk /usr/local/bin/
RUN cd /app
RUN wget http://www.lua.org/ftp/lua-5.3.0.tar.gz
RUN tar zxf lua-5.3.0.tar.gz
COPY lua-5.3.0 /app/
COPY target/classes/lua-5.3.0 /app/
RUN cd /app/lua-5.3.0
RUN apt-get -y install libreadline-dev
RUN make install
RUN cd /app
RUN wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
RUN tar zxvf LuaJIT-2.0.4.tar.gz
COPY LuaJIT-2.0.4 /app/
COPY target/classes/LuaJIT-2.0.4 /app/
RUN cd /app/LuaJIT-2.0.4
RUN make install
RUN cd /app
RUN wget https://www.kyne.com.au/~mark/software/download/lua-cjson-2.1.0.tar.gz
RUN tar -zxvf lua-cjson-2.1.0.tar.gz
COPY lua-cjson-2.1.0 /app/
COPY target/classes/lua-cjson-2.1.0 /app/
RUN cd /app/lua-cjson-2.1.0
COPY target/classes/Makefile /app/lua-cjson-2.1.0/
RUN make
COPY /app/lua-cjson-2.1.0/cjson.so /usr/local/lib/lua/5.1/
COPY /app/lua-cjson-2.1.0/cjson.so /usr/local/include/
wrk -t12 -c400 -d30s http://www.baidu.com
这条命令表示,利用 wrk 对 www.baidu.com 发起压力测试,线程数为 12,模拟 400 个并发请求,持续 30 秒。
wrk --help
Usage: wrk
Options:
-c, --connections Connections to keep open
-d, --duration Duration of test
-t, --threads Number of threads to use
-s, --script Load Lua script file
-H, --header Add header to request
--latency Print latency statistics
--timeout Socket/request timeout
-v, --version Print version details
Numeric arguments may include a SI unit (1k, 1M, 1G)
Time arguments may include a time unit (2s, 2m, 2h)
使用方法: wrk <选项> <被测HTTP服务的URL>
Options:
-c, --connections 跟服务器建立并保持的TCP连接数量
-d, --duration 压测时间
-t, --threads 使用多少个线程进行压测
-s, --script 指定Lua脚本路径
-H, --header 为每一个HTTP请求添加HTTP头
--latency 在压测结束后,打印延迟统计信息
--timeout 超时时间
-v, --version 打印正在使用的wrk的详细版本信息
代表数字参数,支持国际单位 (1k, 1M, 1G)
代表时间参数,支持时间单位 (2s, 2m, 2h)
执行压测命令:
wrk -t12 -c400 -d30s --latency http://www.baidu.com
执行上面的压测命令,30 秒压测过后,生成如下压测报告:
Running 30s test @ http://www.baidu.com
12 threads and 400 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 386.32ms 380.75ms 2.00s 86.66%
Req/Sec 17.06 13.91 252.00 87.89%
Latency Distribution
50% 218.31ms
75% 520.60ms
90% 955.08ms
99% 1.93s
4922 requests in 30.06s, 73.86MB read
Socket errors: connect 0, read 0, write 0, timeout 311
Requests/sec: 163.76
Transfer/sec: 2.46MB
Running 30s test @ http://www.baidu.com (压测时间30s)
12 threads and 400 connections (共12个测试线程,400个连接)
(平均值) (标准差) (最大值)(正负一个标准差所占比例)
Thread Stats Avg Stdev Max +/- Stdev
(延迟)
Latency 386.32ms 380.75ms 2.00s 86.66%
(每秒请求数)
Req/Sec 17.06 13.91 252.00 87.89%
Latency Distribution (延迟分布)
50% 218.31ms
75% 520.60ms
90% 955.08ms
99% 1.93s
4922 requests in 30.06s, 73.86MB read (30.06s内处理了4922个请求,耗费流量73.86MB)
Socket errors: connect 0, read 0, write 0, timeout 311 (发生错误数)
Requests/sec: 163.76 (QPS 163.76,即平均每秒处理请求数为163.76)
Transfer/sec: 2.46MB (平均每秒流量2.46MB)
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)
function delay()
function request()
function response(status, headers, body)
init(args): 由测试线程调用,只会在进入运行阶段时,调用一次。支持从启动 wrk 的命令中,获取命令行参数;
delay(): 在每次发送请求之前调用,如果需要定制延迟时间,可以在这个方法中设置;
request(): 用来生成请求, 每一次请求都会调用该方法,所以注意不要在该方法中做耗时的操作;
response(status, headers, body): 在每次收到一个响应时被调用,为提升性能,如果没有定义该方法,那么wrk不会解析 headers 和 body;
结束阶段:
function done(summary, latency, requests)
done() 方法在整个测试过程中只会被调用一次,我们可以从给定的参数中,获取压测结果,生成定制化的测试报告。
自定义 Lua 脚本中可访问的变量以及方法:
wrk = {
scheme = "http",
host = "localhost",
port = 8080,
method = "GET",
path = "/",
headers = {},
body = nil,
thread = ,
}
request 请求接口
response 返回数据并写入文件
request = function()
wrk.path = "http://qloudpdp.pperf.service.sd/auth/realms/openbanking/protocol/openid-connect/token"
wrk.method = "POST"
wrk.body = "username=openbanking&password=123456&client_id=resource-proxy&client_secret=4a9af65a-5af8-4b3e-8f64-8929272e2433&grant_type=password"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
print("step2",2)
return wrk.format("POST" , "http://qloudpdp.pperf.service.sd/auth/realms/openbanking/protocol/openid-connect/token")
end
response = function(status, headers, body)
if status == 200 then
print("step3",3)
local cjson = require("cjson")
access_token = cjson.decode(body). access_token
print("access_token",access_token)
body ="audience=resource-proxy&grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&permission=48c539d6-2dc6-434b-b2d7-d4eb09a9287a&subject_token="..access_token
-- token 保存
file = io.open("get-ticket-auth.lua", "w")
io.output(file)
io.write('wrk.method = "POST"',"\n")
io.write('wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"',"\n")
io.write('wrk.headers["Authorization"] = "Basic cmVzb3VyY2UtcHJveHk6NGE5YWY2NWEtNWFmOC00YjNlLThmNjQtODkyOTI3MmUyNDMz"',"\n")
io.write('wrk.body =','"'..body..'"',"\n")
io.close(file)
print("写入token")
end
end
wrk -t1 -c1 -d1s -s /app/operattoken.lua http://pdpip地址/auth/realms/openbanking/protocol/openid-connect/token
wrk.method = "POST"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"
wrk.headers["Authorization"] = "Basic cmVzb3VyY2UtcHJveHk6NGE5YWY2NWEtNWFmOC00YjNlLThmNjQtODkyOTI3MmUyNDMz"
wrk.body ="audience=resource-proxy&grant_type=urn:ietf:params:oauth:grant-type:uma-ticket&permission=48c539d6-2dc6-434b-b2d7-d4eb09a9287a&subject_token=$token1"