https://www.cnblogs.com/poloyy/p/14872021.html
wrk性能测试工具的使用:
下载:
https://github.com/giltene/wrk2
安装:
yum -y install gcc automake autoconf libtool make
yum install gcc++
yum install openssl-devel 或者
yum install libssl-dev
# git clone https://github.com/giltene/wrk2.git 下载源码
# cd wrk2 安装目录
# make
ln -s /export/ccc/wrk2-master/wrk /usr/local/bin
参数设定经验:
线程数: -t 依据cpu核数来设定,最大值不要超过2倍cpu核数
连接数:-c 并发数,连接数需要在测试过程中多次调试,找到QPS达到最大临界点的
最大并发量;由于服务器有自身的负载极限,也会出现连接数越大QPS越低的情况,这种情况是因为
连接数设置的过高,导致待测系统超出自身能承受的负载。
吞吐量: -R 是每个线程每秒完成的请求数,这个数值是wrk2必带的一个参数,在测试过程中
也是需要测试人员多次调试,通过不断上调其数值,测试出QPS的临界值及保证服务
可用的时延。
命令:
path: 该字符串会拼到 http://ip 后
wrk.format 介绍:{
根据参数和全局变量wrk生成一个http请求函数签名:
function wrk.format(method, path, headers, body)
method: 请求方法
path: 路径
headers: 请求头
body: 参数
}
7.lua声明周期
共有三个阶段,启动阶段,运行阶段,结束阶段
启动阶段:
function setup(thread) :
wrk会在线程初始化但还没有启动的时候调用setup(thread)方法。且每个线程都会调用一次,并传入测试线程的对象thread作为参数。
thread.addr 设置请求需要打到的ip
thread:get(name) 获取线程全局变量
thread:set(name, value) 设置线程全局变量
thread:stop() 终止线程
运行阶段:
function init(args) -- 每个线程都会先调用1次,其中可以做一些初始化工作,比如读测试数据
delay() -- 每次请求调用1次,发送下一个请求之前的延迟, 单位为ms
function request() -- 每次请求调用1次,返回http请求
function response(status, headers, body) -- 每次请求调用1次,返回http响应
lua脚本:
#testcase1:
-------------------------------
#wrk -t1 -c1 -d1s --latency -R 1 -s test.lua http://10.50.36.40/
#test.lua压测脚本内容:这里模拟一个post请求,data为消息体,每次请求生成一个uuid,保证数据的不重复
request= function()
local uuid = io.open("/proc/sys/kernel/random/uuid", "r"):read()
local data = [[{
"table_data":[
{
"create_time":"2021-02-03 21:34:44",
"description":"%s"}
],
"table_name":"tab_record"
}]]
wrk.method = "POST"
wrk.body =string.format(data,tostring(uuid))
wrk.headers["Content-Type"] = "application/json"
return wrk.format()
end
#testcase2:
------------------------------
#发送随机参数
request = function()
num = math.random(1000,9999)
path = "/test.html?t=" .. num
return wrk.format("GET", path)
end
#testcase3:
----------------------------------------------------------------
#从文件中依次选择参数,适用于多条固定的参数测试(table.getn()是获取集合的长度)
idArr = {}
falg = 0
function init(args)
for line in io.lines("ids.txt") do
print(line)
idArr[falg] = line
falg = falg + 1
end
falg = 0
end
request = function()
local path ="/getInfo?id=%s"
parms = idArr[falg%(table.getn(idArr) + 1)]
path = string.format(path,parms)
falg = falg + 1
return wrk.format(nil, path)
end
#testcase4:
---------------------------------------------------
#发送多个请求:
init = function(args)
local r = {}
r[1] = wrk.format(nil, "/info/getInfoById?id=100001&channel=0")
r[2] = wrk.format(nil, "/info/getByName?name=aaa&startindex=0&length=10")
r[3] = wrk.format(nil, "/info/getByUserId?id=88888888")
req = table.concat(r)
end
request = function()
return req
end
#testcase5:
----------------------------------------------------------
-- example script that demonstrates use of setup() to pass
-- data to and from the threads
local counter = 1
local threads = {}
function setup(thread)
-- 给每个线程设置一个 id 参数
thread:set("id", counter)
-- 将线程添加到 table 中
table.insert(threads, thread)
counter = counter + 1
end
function init(args)
-- 初始化两个参数,每个线程都有独立的 requests、responses 参数
requests = 0
responses = 0
-- 打印线程被创建的消息,打印完后,线程正式启动运行
local msg = "thread %d created"
print(msg:format(id))
end
function request()
-- 每发起一次请求 +1
requests = requests + 1
return wrk.request()
end
function response(status, headers, body)
-- 每得到一次请求的响应 +1
responses = responses + 1
end
function done(summary, latency, requests)
-- 循环线程 table
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
#testcase6:
---------------------------------------------------
--导入Lua库
local json = require "json"
local md5 = require "md5"
local random = math.random
local uuid = require 'uuid'
-- 声明一些实际工作中,接口需要用的的变量
local secret = "platform_secret"
local pkg_info = {
is_simulator = false
}
-- 提前声明请求体
local req = {
game = "",
secret = "b",
server = "c",
guest = false,
platform = "d",
pkg_info = pkg_info
}
-- 修改请求头,所有请求均生效
wrk.headers["Content-Type"] = "application/json"
-- 官方例子的写法,这里加上
local counter = 1
local threads = {}
function setup(thread)
thread:set("id",counter)
table.insert(threads,thread)
counter = counter + 1
end
function init(args)
math.randomseed(id)
end
local upv = 100000000
-- 自定义一个方法
local function random_uid()
return 'testuid' .. tostring(upv * id + random(0,upv))
end
--自定义一个方法,并返回字符串
function create_UUID()
local template = "xxxxxxxxxxxxxxxxxxxxx"
d = io.open("/dev/urandom","r"):read(4)
math.randomseed(os.time() + d:byte(1) + (d:byte(2) * 256) + (d:byte(3) * 65536) + (d:byte(4) * 42949
67296))
return string.gsub(template,"x",function(c)
local v = (c == "x") and math.random(0,0xf) or math.random(8,0xb)
return string.format("%x", v)
end)
end
function request()
--给 req 对象加两个参数pid、ptokn
req.pid = uuid.generate()
req.ptoken = md5.sumhexa(req.pid .. secret)
--打印下看看对不对
print(json.encode(req))
--返回自定义的HTTP请求字符串,动态创建了一个请求
return wrk.format("POST". wrk.path. wrk.headers. json.encode(req))
function response(status, headers, body)
-- 如果响应码 != 200 则打印 body 并且返回
if status ~= 200 then
print(body)
return
end
-- 打印响应体(仅调试用,正式测试需要注释掉print)
local resp = json.decode(body)
print(body)
-- 如果响应体的 code != 0 (一般就是后端返回码错误码)
if resp.code ~= 0 then
-- 打印body,并返回
print(json.encode(req)..'-->'..body)
return
end
end
--导入 Lua 库
local json = require "json"
local md5 = require "md5"
local random = math.random
local uuid = require 'uuid'
-- 声明一些实际工作中,接口需要用到的变量
local secret = "platform_secret"
local pkg_info = {
is_simulator = false
}
-- 提前声明请求体
local req = {
game = "",
secret = "b",
server = "c",
guest = false,
platform = "d",
pkg_info = pkg_info
}
-- 修改请求头,所有请求均生效
wrk.headers["Content-Type"] = "application/json"
-- 官方例子的写法,这里加上
local counter = 1
local threads = {}
function setup(thread)
thread:set("id",counter)
table.insert(threads,thread)
counter = counter + 1
end
function init(args)
math.randomseed(id)
end
local upv = 100000000
-- 自定义一个方法
local function random_uid()
return 'testuid' .. tostring(upv * id + random(0,upv))
end
-- 自定义一个方法,并返回字符串
function create_UUID()
local template = "xxxxxxxxxxxxxxxxxxxxx"
d = io.open("/dev/urandom","r"):read(4)
math.randomseed(os.time() + d:byte(1) + (d:byte(2) * 256) + (d:byte(3) * 65546) + (d:byte(4) * 4294967296))
return string.gsub(template,"x",function(c)
local v = (c == "x") and math.random(0,0xf) or math.random(8,0xb)
return string.format("%x",v)
end)
end
function request()
-- 给req 对象加两个参数pid、ptoken
req.pid = uuid.generate()
req.ptoken = md5sumhexa(req.pid .. secret)
-- 打印下看看对不对
print(json.encode(req))
-- 打印下看看对不对
print(json.encode(req))
-- 返回自定义的 HTTP 请求字符串,动态创建了一个请求
return wrk.format("POST". wrk.path. wrk.headers. json.encode(req))
function response(status, headers, body)
-- 如果响应码 != 200 则打印 body 并且返回
if status ~= 200 then
print(body)
return
end
-- 打印响应体(仅调试用,正式测试需要注释掉 print)
local resp = json.decode(body)
print(body)
-- 如果响应体的 code != 0 (一般就是后端返回码错误)
if resp.code ~= 0 then
-- 打印body,并返回
print(json.encode(req)..'-->'..body)
return
end
end