简单压测http-wrk

关于压测

常见的系统开发过程,压测总是被置于整个周期的末尾,比如项目基本功能开发完成或者临近上线时才开始准备压测。这个时候往往累积了大量的“小问题”,导致压测进行的比较缓慢,如果遇到前期“一压就崩”的状态则更让人奔溃。按照我的个人经验,压测之所以被经常性的忽略,不外乎压测脚本编写麻烦,场景梳理费时费力,而且特别占用开始时间等因素。其实如果不考虑复杂的业务场景,可以使用wrk/ad等简单http压测工具对刚完成开发的接口进行针对性压测,可以帮助后端开发人员更早的发现性能上的问题。

wrk

wrk 是一个简单小巧的 http 性能测试工具,只有一个命令行,就能做很多基本的 http 性能测试。

wrk 本身是开源项目,代码在 github 上:https://github.com/wg/wrk

安装

wrk 具体的安装过程可以参考其 github上的wiki:https://github.com/wg/wrk/wiki

本质上wrk只能运行在类Unix 的系统上,所以Win10其实要开启WSL(Windows SubLinux)才能正常安装使用。当然,官方wiki里都有提及,按照wiki中的提示操作即可。

一键压测

如果针对一个GET请求的Http接口,wrk基本上可以一键完成,比如:

# 使用wrk创建12个线程
# 维持 200 http并发连接
# 对指定接口【GET www.baidu.com】进行持续30秒的压测
wrk -t12 -c200 -d30s https://www.baidu.com
压测baidu

wrk命令的详细选项如下:

  • -c, --connections: http并发数(默认使用http1.1,会复用TCP链接)
  • -d, --duration: 持续压测时间, 比如: 2s, 2m, 2h
  • -t, --threads: 总线程数(建议为核心数的2倍即可)
    --s, --script: 指定执行Lua脚本(可以使用Lua脚本实现更高阶的功能)
  • -H, --header: 添加http header, 比如. -H 'Authorization: Bearer {token_value}' 来添加接口认证信息
  • --latency: 在控制台打印出延迟统计情况
  • --timeout: http超时时间

用过lua脚本处理更复杂的情况

用命令行其实已经可以覆盖很多简单的场景了。但是如果http接口稍微复杂些,就需要使用Lua脚本辅助。比如 接口为POST类型,body中有参数,响应需要写断言等等。

比如下面这个简单的lua脚本,修改了全局对象wrk的三个属性,method,body,headers,最终所有发出的http请求都会被影响。

wrk.method = "POST"
wrk.body   = "foo=bar&baz=quux"
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

Lua脚本执行的简单理解

想要编写更加复杂的Lua脚本,需要了解wrk提供的几个hook函数。

wrk提供的hook函数

wrk 提供了几个 hook 函数,可以用 lua 来编写一些复杂场景下的测试:

  • setup

这个函数在目标 IP 地址已经解析完,并且所有 thread 已经生成,但是还没有开始时被调用,每个线程执行一次这个函数。可以通过 thread:get(name), thread:set(name, value) 设置线程级别的变量。

  • init

每次请求发送之前被调用。可以接受 wrk 命令行的额外参数,通过 – 指定。

  • delay

这个函数返回一个数值,在这次请求执行完以后延迟多长时间执行下一个请求,可以对应 thinking time 的场景。

  • request

通过这个函数可以每次请求之前修改本次请求的属性,返回一个字符串,这个函数要慎用, 会影响测试端性能。

  • response

每次请求返回以后被调用,可以根据响应内容做特殊处理,比如遇到特殊响应停止执行测试,或输出到控制台等等。

这里提供一个我自己使用的简单lua脚本

-- 打印respose到控制台
response = function(status, headers, body)
    -- 这里其实可以解析body,写断言,针对性打印比较好
    print("status:", status)
    print("body:", body)
end

-- 自定义分析压测结果
done = function(summary, latency, requests)

    local durations=summary.duration / 1000000    -- 执行时间,单位是秒
    local errors=summary.errors.status            -- http status不是200,300开头的
    local requests=summary.requests               -- 总的请求数
    local valid=requests-errors                   -- 有效请求数=总请求数-error请求数
  
    io.write("Durations:       "..string.format("%.2f",durations).."s".."\n")
    io.write("Requests:        "..summary.requests.."\n")
    io.write("Avg RT:          "..string.format("%.2f",latency.mean / 1000).."ms".."\n")
    io.write("Max RT:          "..(latency.max / 1000).."ms".."\n")
    io.write("Min RT:          "..(latency.min / 1000).."ms".."\n")
    io.write("Error requests:  "..errors.."\n")
    io.write("Valid requests:  "..valid.."\n")
    io.write("QPS:             "..string.format("%.2f",valid / durations).."\n")
    io.write("--------------------------\n")
  
end

wrk源码中提供了一些常见的Lua脚本demo,可以参考:https://github.com/wg/wrk/tree/master/scripts

建议

其实这个建议就是官方的readme,简单翻一下:

如果仅仅更改HTTP方法,修改路径,添加标头或正文的Lua脚本不会对压测的性能产生影响。但是针对每个请求的操作(特别是构建新的HTTP请求)以及使用 response()函数 必然会减少可以生成的负载量。

A user script that only changes the HTTP method, path, adds headers or a body, will have no performance impact. Per-request actions, particularly building a new HTTP request, and use of response() will necessarily reduce the amount of load that can be generated.

小技巧

-H参数和curl-H参数含义一致,所以在实际使用中可以先使用curl确认编写的命令是否正确,或者也可以使用postman来确认,然后使用postman生成curl的请求命令即可。

使用 postman 生成 curl 命令

参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容