8

WRK:一个可编程的HTTP性能测试工具

 4 years ago
source link: https://blog.huoding.com/2019/08/19/763
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
← 上一篇 下一篇 →

WRK:一个可编程的HTTP性能测试工具

发表于2019-08-19

同 ab 这种单线程 HTTP 性能测试工具相比,wrk 是一个足够现代化的 HTTP 性能测试工具,最重要的特性是:它是可编程的,借助内嵌 lua,我们可以控制测试的全过程。

关于 wrk 中 lua 扩展的数据结构,可以参考官方源代码中的 wrk.lua 文件:

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

此外,还有一些钩子方法可供使用:

  • setup(thread):启动阶段执行,每个线程调用一次
  • init(args):运行阶段执行,每个线程调用一次
  • delay(),运行阶段执行,每个请求调用一次
  • request(),运行阶段执行,每个请求调用一次
  • response(status, headers, body),运行阶段执行,每个请求调用一次
  • done(summary, latency, requests),结束阶段执行,整个过程调用一次

多数情况下,我们只要关注 request 钩子方法即可,通过它我们可以自定义请求的各个参数,如果想要了解更多的用法,可以参考官方源代码的 scripts 目录。

让我们动手实战一下,假设一个网站,主要的请求有三种,分别是:

  • /a:GET 请求,占比 20%
  • /b:GET 请求,占比 30%
  • /c:POST 请求,占比 50%

结合前面提到的 wrk 中 lua 扩展的相关知识,我们可以实现如下代码:

-- benchmark.lua

math.randomseed(os.time())

local config = {
    {num=20, path="/a"},
    {num=30, method="get", path="/b"},
    {num=50, method="post", path="/c", body="foo=x&bar=y"},
}

local requests = {}

for i, request in ipairs(config) do
    if request.method then
        request.method = string.upper(request.method)
    end

    for _ = 1, request.num do
        requests[#requests + 1] = i
    end
end

local length = #requests

for _ = 1, length do
    local m, n = math.random(length), math.random(length)
    requests[m], requests[n] = requests[n], requests[m]
end

local count = 0

function request()
    local i = (count % length) + 1
    local request = config[requests[i]]
    count = count + 1

    return wrk.format(
        request.method,
        request.path,
        request.headers,
        request.body
    )
end

代码逻辑很简单,无非就是根据配置信息生成一个大数组,然后把数据随机化一下,每个请求来的时候,根据计数器直接给一条数据即可。

我在我的笔记本上以此脚本为例实际跑了一个 100 并发的例子,这里有个题外话需要提一下,很多人做 benchmark 只关注 rps,却忽略了 latency,这是不严谨的,设想一个网站的 rps 数据很好,但是总有一定百分比的请求出现高 latency,依然是有问题的:

shell> wrk -c 100 -s ./benchmark.lua http://localhost

Running 10s test @ http://localhost
  2 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     4.26ms    1.04ms  23.95ms   94.87%
    Req/Sec    11.85k   662.52    13.08k    67.50%
  235787 requests in 10.00s, 71.95MB read
  Non-2xx or 3xx responses: 0
Requests/sec: 23573.71
Transfer/sec: 7.19MB

在测试的时候我顺手用 ngrep 监控了一下请求:

ngrep -W byline ” ‘dst port 80’

如图可见,wrk 随机发送了不同的请求,完美!

此条目由老王发表在Technical分类目录,并贴了Benchmark标签。将固定链接加入收藏夹。

发表评论 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注

评论

显示名称 *

电子邮箱地址 *

网站网址


Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK