wrk性能测试工具使用

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

请尊重笔者的劳动成果哦,转载请说明出处哦
原文地址:https://www.cnblogs.com/gufengchen/p/15737173.html