• wrk压测工具使用


    介绍分为四部分

      1.wrk简述

      2.wrk安装

      3.wrk运行参数

      4.wrk高级用法

    1.wrk简述

    当使用ab做压测的时候发现,ab的客户端消耗很大,而且测试时性能较差,测试redis,spring boot时性能都与官方介绍相差太多,由此引入wrk.

    wrk是一款简单的HTTP压测工具,托管在Github上, https://github.com/wg/wrk.
    wrk 的一个很好的特性就是能用很少的线程压出很大的并发量. 原因是它使用了一些操作系统特定的高性能 io 机制, 比如 select, epoll, kqueue 等. 其实它是复用了 redis 的 ae 异步事件驱动框架. 确切的说 ae 事件驱动框架并不是 redis 发明的, 它来至于 Tcl的解释器 jim, 这个小巧高效的框架, 因为被 redis 采用而更多的被大家所熟知.
    wrk源码涉及到很多系统内核的调用,指望另有大神阅读并出示解释,引用一篇:https://blog.csdn.net/codingwithme/article/details/52251451

    2.wrk安装

    在mac上可以使用brew安装:

    brew install wrk

    也可以使用源码安装:

     git clone https://github.com/wg/wrk.git
     cd wrk
     make

    3.wrk运行参数

    wrk常规操作:

    wrk -t15 -c300 -d10 --latency -s generateIDCode.lua http://localhost:14077/test

    -t : thread 开启线程数

    -c : connection 服务端连接数

    -d : during 测试时间

    —latency : 显示时延分布

    结果如下:

    Running 10s test @ http://10.1.4.55:14077/test
      15 threads and 300 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     5.89ms   12.65ms 244.40ms   98.05%
        Req/Sec     4.40k     0.86k    6.15k    82.42%
      Latency Distribution
         50%    3.88ms
         75%    5.59ms
         90%    8.28ms
         99%   31.96ms
      657863 requests in 10.10s, 53.33MB read
    Requests/sec:  65137.56
    Transfer/sec:      5.28MB

    这里面比较复杂的是lua脚本的编写,正常http,post访问需要提供一份lua脚本:

    wrk.method = "POST"
    wrk.headers["Content-Type"] = "application/json"
    wrk.body = '{"header": {"requestTime": "2018100910320000","requestSeq": "e379853d-d93e-4249-b9be-8a272b","appId": "bc1f4a2a995b47db9018031801984857"},"content": {"duration": "300","idCard": "350123199502150000sfsdafwjdhsjofwofnsdfnjdwfnew1561651dsfsdnklndsjfn1165165165fdsfhweufwehfjdsnfiefenf350123199502150000sfsdafwjdhsjofwofnsdfnjdwfnew1561651dsfsdnklndsjfn1165165165fdsfhweufwehfjdsnfiefenf350123199502150000","expressParam": "expressParamexpressParaexpres","name": "name","isPic": "0","availableTimes": "5"}}'

    到这里就满足大多数情况的压测使用了.只不过我们习惯性拓展一下:

    这里要记录wrk用这种方式提供了哪些可自定义的东西

    变量值:

    wrk = {
      scheme  = "http",
      host    = "localhost",
      port    = nil,
      method  = "GET",
      path    = "/",
      headers = {},
      body    = nil,
      thread  = <userdata>,
    }

    方法:

    -- 生成整个request的string,例如:返回
    -- GET / HTTP/1.1
    -- Host: tool.lu
    function wrk.format(method, path, headers, body)
    
    -- 获取域名的IP和端口,返回table,例如:返回 `{127.0.0.1:80}`
    function wrk.lookup(host, service)
    
    -- 判断addr是否能连接,例如:`127.0.0.1:80`,返回 truefalse
    function wrk.connect(addr)
    
    
    function setup(thread)
    
    -- thread提供了1个属性,3个方法
    -- thread.addr 设置请求需要打到的ip
    -- thread:get(name) 获取线程全局变量
    -- thread:set(name, value) 设置线程全局变量
    -- thread:stop() 终止线程
    
    function init(args)
    -- 每个线程仅调用1次,args 用于获取命令行中传入的参数, 例如 --env=pre
    
    function delay()
    -- 每个线程调用多次,发送下一个请求之前的延迟, 单位为ms
    
    function request()
    -- 每个线程调用多次,返回http请求
    
    function response(status, headers, body)
    -- 每个线程调用多次,返回http响应
    
    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
      }
    }

    4.wrk高级用法

    两个例子:例子是网上找的,但是这两个功能是最实用的,其他方法变量用到的场景都比较少:

    1.请求时,打印response内容:

    function response(status, headers, body)
          print(body)
    end

    2.请求时,构造变动的随机id:

    request = function()
        counter = counter + 1
        local task_id = string.format("%d-%s", os.time()*10000+math.random(1, 10000), randomString(10))
     
        local data = [[{
            "task_timeout": 30,
            "task_id": "%s",
            "task_body": {
                "url_list": [
                {
                    "subtask_id": "1000000022511092",
                    "url": "http://zhihu.com/upic/2017/08/24/15/kk.webp",
                    "force": true
                },
                {
                    "subtask_id": "1000000022511093",
                    "url": "http://zhihu.com/upic/2017/08/24/15/zz.jpg",
                    "force": true
                }
                ]
            },
            "ip_list": [],
            "ip_list_flag": false,
            "task_type": "refresh",
            "retry_failed": false,
            "working_layer": "polymerization"
        }]]
     
        wrk.method = "POST"
        wrk.body   = string.format(data, tostring(task_id))
        wrk.headers["Content-Type"] = "application/json"
        -- return wrk.format("POST", "/v1/engine/task")
        return wrk.format()
     
    end

     以及:

    local queries = {
        "language=php",
        "language=java",
        "language=lua"
    }
    local i = 0
    request = function()
        local body = wrk.format(nil, nil, nil, queries[i % #queries + 1])
        i = i + 1
        return body
    end

     

     

  • 相关阅读:
    Azure Messaging-ServiceBus Messaging消息队列技术系列6-消息回执
    Azure Messaging-ServiceBus Messaging消息队列技术系列7-消息事务
    Azure Messaging
    消息队列技术之基本概念
    Azure IoT 技术研究系列1
    Azure IoT 技术研究系列3
    Azure IoT 技术研究系列2
    Azure IoT 技术研究系列4
    memset()
    C++ GetComputerName()
  • 原文地址:https://www.cnblogs.com/garfieldcgf/p/10002698.html
Copyright © 2020-2023  润新知