2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > 性能测试工具-WRK

性能测试工具-WRK

时间:2023-07-07 21:32:11

相关推荐

性能测试工具-WRK

性能测试工具-WRK使用

1.简介

wrk是一款针对http协议的基准测试工具,它能够在单机多核CPU的条件下,使用系统自带的高性能 I/O机制,如epoll,kqueue等,通过多线程和事件模式,对目标机器产生大量的负载。

2.优劣势

2.1优势:

轻量级性能测试工具;安装简单(相对 Apache ab 来说);学习曲线基本为零,几分钟就能学会咋用了;基于系统自带的高性能 I/O 机制,如 epoll, kqueue, 利用异步的事件驱动框架,通过很少的线程就可以压出很大的并发量;

2.2劣势:

wrk 目前仅支持单机压测,后续也不太可能支持多机器对目标机压测,因为它本身的定位,并不是用来取代 JMeter, LoadRunner 等专业的测试工具,wrk 提供的功能,对我们后端开发人员来说,应付日常接口性能验证还是比较友好的。

3.wrk安装

CentOS / RedHat / Fedora的系统安装方法

sudo yum groupinstall 'Development Tools'sudo yum install -y openssl-devel git git clone /wg/wrk.git wrkcd wrkmake# 将可执行文件移动到 /usr/local/bin 位置sudo cp wrk /usr/local/bin

Ubuntu/Debian系统上的安装方法

依次执行如下命令:sudo apt-get install build-essential libssl-dev git -ygit clone /wg/wrk.git wrkcd wrkmake# 将可执行文件移动到 /usr/local/bin 位置sudo cp wrk /usr/local/bin

使用方法: wrk <选项> <被测HTTP服务的URL>

Options:

-c, --connections 跟服务器建立并保持的TCP连接数量

-d, --duration 压测时间

-t, --threads 使用多少个线程进行压测

-s, --script<S> 指定Lua脚本路径 -H, --header<H> 为每一个HTTP请求添加HTTP头--latency在压测结束后,打印延迟统计信息 --timeout<T> 超时时间-v, --version打印正在使用的wrk的详细版本信息

代表数字参数,支持国际单位 (1k, 1M, 1G)

代表时间参数,支持时间单位 (2s, 2m, 2h)

当看到如下提示信息说明安装成功

[root@standalone wrk-master]# wrk -v

wrk [epoll] Copyright © Will Glozer

Usage: wrk

Options:

-c, --connections Connections to keep open

-d, --duration Duration of test

-t, --threads Number of threads to use

-s, --script<S> Load Lua script file -H, --header<H> Add header to request--latencyPrint latency statistics --timeout<T> Socket/request timeout-v, --versionPrint version details

Numeric arguments may include a SI unit (1k, 1M, 1G)

Time arguments may include a time unit (2s, 2m, 2h)

[root@standalone wrk-master]#

## 4.wrk简单使这里使用java构建一个简单的服务应用代码:服务端程序接收参数,然后给出响应,响应是一个随机数。```java@RestController@RequestMapping("/demo")public class WrkServerTestFacade {private Random rand = new Random();@RequestMapping(value = "/get",method = {RequestMethod.GET})public int getData() {return rand.nextInt();}}@SpringBootApplicationpublic class WrkApplication {public static void main(String[] args) {SpringApplication.run(WrkApplication.class, args);}}

这是一个简单版本的wrk服务测试。先启动java服务,进行一个简单的压力测试

[root@standalone ~]# wrk -t2 -c1000 -d10s --latency http://192.168.3.107:8080/demo/getRunning 10s test @ http://192.168.3.107:8080/demo/get2 threads and 1000 connectionsThread Stats AvgStdevMax +/- StdevLatency 94.91ms 77.27ms 1.62s 87.84%Req/Sec5.19k2.00k 12.19k 71.02%Latency Distribution50% 75.09ms75% 110.86ms90% 175.86ms99% 351.70ms99264 requests in 10.05s, 14.02MB readSocket errors: connect 0, read 0, write 0, timeout 8Requests/sec: 9873.74Transfer/sec:1.39MB

这条命令的意思是:使用10个线程、1000个连接、持续10秒,对 http://192.168.16.151:8080/demo/get这个地址进行压力测试。

压测报告说明

Running 10s test @ http://192.168.3.107:8080/demo/get2 threads and 1000 connections(使用2个线程和1000个连接)(线程数据)(平均) (标准差) (最大值) (正负一个标准差)Thread Stats AvgStdevMax +/- Stdev延迟Latency 94.91ms 77.27ms 1.62s 87.84%请求/秒Req/Sec5.19k2.00k 12.19k 71.02%Latency Distribution50% 75.09ms(50% 的请求在75毫秒内)75% 110.86ms(75%的请求在110毫秒内)90% 175.86ms(90%的请求在172毫秒内)99% 351.70ms(99%的请求在351毫秒内)99264 requests in 10.05s, 14.02MB readSocket errors: connect 0, read 0, write 0, timeout 8 存在在8个超时的错误Requests/sec: 9873.74 (QPS,平均每秒的请求数)Transfer/sec:1.39MB (每秒传输1.39MB的流量)

标准差,简单来说,标准差是一组数据平均值分散程度的一种度量。一个较大的标准差,代表大部分数值和其平均值之间差异较大;一个较小的标准差,代表这些数值较接近平均值。标准差如果太大说明样本本身离散程度比较高,有可能系统性能波动较大。

修改参数再来做一个测试

[root@standalone ~]# wrk -t2 -c128 -d10s --latency http://192.168.3.107:8080/demo/getRunning 10s test @ http://192.168.3.107:8080/demo/get2 threads and 128 connectionsThread Stats AvgStdevMax +/- StdevLatency9.12ms 7.66ms 116.17ms 90.08%Req/Sec5.24k2.51k 9.93k 56.02%Latency Distribution50% 6.49ms75% 11.56ms90% 16.20ms99% 41.09ms103036 requests in 10.06s, 14.56MB readRequests/sec: 10246.51Transfer/sec:1.45MB[root@standalone ~]#

当连接数降低至128时。可以发现,平时的时延降低了很多。

128个连接时50%的时延在6.49ms,而1000的连接时延在75.09ms.降低了好几个量级。

这样可以发现每秒的请求数也有所提升。从1000个的9873,提升至10246个。

PS:关于线程数和连接数,差不是越大越好,大太将导致线程的上下文切换频繁,反而降低了性能,而太小又不足以发挥性能。这必然是一个针对机器压测后的一个实际数据。

一般的做法是区分,CPU密集型或者I/O密集型,

CPU密集型,最大不能超过CPU核心+1,再大将导致性能都浪费在上下文切换中,

I/O密集型,此配制可以CPU核数的2倍,或核心数数的4倍,因为I/O不需要过多的CPU参与,反正是等待回复,所以可以设置这么多的线程数,但如果超过一个极限,也将导致过多的上下文 切换,反而浪费了性能。

5.高级用法-携带动态参数。

再来个常用的带参数的请求。

@RestController@RequestMapping("/demo")public class WrkServerTestFacade {private Random rand = new Random();@RequestMapping(value = "/post",method = {RequestMethod.POST})public int getDataPost(@RequestBody PostData data) {System.out.println("data :" + data);return rand.nextInt();}}class PostData {private Integer data;private String name;public Integer getData() {return data;}public void setData(Integer data) {this.data = data;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {final StringBuilder sb = new StringBuilder("PostData{");sb.append("data=").append(data);sb.append(", name='").append(name).append('\'');sb.append('}');return sb.toString();}}

先用其他工具测试下:

然后再来开始使用wrk进行参数的压测。

也同样先给出测试用的lua脚本

测试脚本1:

wrk.method="POST"wrk.headers["Content-Type"]="application/json"wrk.body= '{"data": 1111,"name" : "name"}'

一个固定的json字符串请求,使用post

[root@standalone lua]# wrk -t2 -c256 -d10s --latency -s post.lua http://192.168.3.107:8080/demo/postRunning 10s test @ http://192.168.3.107:8080/demo/post2 threads and 256 connectionsThread Stats AvgStdevMax +/- StdevLatency 16.08ms 11.96ms 142.69ms 81.92%Req/Sec4.22k1.85k 8.23k 63.64%Latency Distribution50% 12.53ms75% 21.55ms90% 30.76ms99% 60.80ms82841 requests in 10.09s, 11.71MB readRequests/sec: 8211.46Transfer/sec:1.16MB[root@standalone lua]#

测试脚本2

wrk.method="POST"wrk.headers["Content-Type"]="application/json"function request()user = '{"data":'..math.random(1,3000000)..',"name":"name"}'return wrk.format('POST',nil,nil,user)end

通过脚本生成测试的相关的动态的json串发送

[root@standalone lua]# wrk -t2 -c256 -d10s --latency -s post2.lua http://192.168.3.107:8080/demo/postRunning 10s test @ http://192.168.3.107:8080/demo/post2 threads and 256 connectionsThread Stats AvgStdevMax +/- StdevLatency 18.72ms 13.57ms 126.21ms 84.49%Req/Sec4.24k2.06k 7.82k 54.95%Latency Distribution50% 14.46ms75% 23.14ms90% 35.22ms99% 70.27ms82668 requests in 10.06s, 11.68MB readRequests/sec: 8213.75Transfer/sec:1.16MB[root@standalone lua]#

6.wrk的lua脚本说明

wrk支持在三个阶段对进行个性化的设置,分别启动阶段、运行阶段、和结束阶段。每个运行线程都拥有独立的lua运行环境。

6.1 启动阶段

function setup(thread)

在脚本中实现setup方法,wrk就会在测试线程已经初始化、但还没有启动的时候调用。wrk会为每一个测试线程调用一次setup方法,并传入代表测试线程的对象thread作为参数,setup可操作thread对象,获取信息、存储信息、甚至关闭线程。

thread.addr - get or set the thread's server addressthread:name(name) - get the value of a global in the thread's envthread:set(name,value) -set the value of a global in the thread envthread:stop() - stop the thread

6.2 运行阶段

funcation init(args)function delay()function request()function respone(status,headers,body)

init(args)由测试线程调用,只会在进入运行阶段时调用一次,支持从启动的wrk的命令行中获取命令行参数。

delay()在每次发送请求之前调用,如果需要定制延时时间可以在这个方法中设置。

request()用来生成请求,每一次请求都会调用该方法,注意不要在此方法做耗时操作。

respone(status,headers,body)每一次收到响应时被调用,为提升性能、如果没有定义该方法,wrk不会解析header和body;

6.3 结束阶段

function done(summary,latency,requests)

done()方法在整个测试过程中仅会被调用一次,可以从给定的参数中获取压测结果。生成定制化的压测报告。

6.4 自定义lua脚本可访问的变量

wrk变量

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

以上是wrk的全局变量,个性该wrk变量会影响所有的请求。

6.5 自定义脚本可使用方法

wrk.format

wrk.lookup

wrk.connect

#wrk format returns a HTTP request string containing the passed parameters merged with values from the wrk table.#wrk format 返回一个http请求的字符串 包括传递的参数和全局参数wrkfunction wrk.format(method,path,headers,body)#wrk.lookup return a table containing all know address for the host and server pair. the correponds to the POSIX getaddress() #ftunction # wrk.lookup 返回一个包含主机和所有已知地址的表。这对应于POSIX的getaddress方法function wrk.lookup(host,service) #wrk.connect returns true if the address can be connected to ,otherwise it return false, the address must be one returned from #wrk.lookup().#测试服务是否可用,能连接返回true,否则返回false,这个地址必须是wrk.lookup返回的地址function wrk.connect(addr)

7. 测试会话保持的压力测试

这是个常用的功能,先进行服务器的用户登录。再进行接口压力测试。

先看下服务端的程序。同样使用一个java的后台服务

@RestController@RequestMapping("/demo")public class WrkServerTestFacade {public static final String SESSION_ID = "SESSION_ID";/*** 执行登录操作** @param data* @param request* @return*/@RequestMapping(value = "/login",method = {RequestMethod.POST})public int login(@RequestBody PostData data, HttpServletRequest request) {PostData userDat = (PostData) request.getSession().getAttribute(SESSION_ID);if (userDat == null) {request.getSession().setAttribute(SESSION_ID, data);}return 1;}/*** 执行登录操作** @param request* @return*/@RequestMapping(value = "/getUser",method = {RequestMethod.GET})public String getUser(HttpServletRequest request) {PostData userDat = (PostData) request.getSession().getAttribute(SESSION_ID);if (null == userDat) {return "this is null";}return userDat.toString();}}class PostData {private Integer data;private String name;public Integer getData() {return data;}public void setData(Integer data) {this.data = data;}public String getName() {return name;}public void setName(String name) {this.name = name;}@Overridepublic String toString() {final StringBuilder sb = new StringBuilder("PostData{");sb.append("data=").append(data);sb.append(", name='").append(name).append('\'');sb.append('}');return sb.toString();}}@SpringBootApplicationpublic class WrkApplication {public static void main(String[] args) {SpringApplication.run(WrkApplication.class, args);}}

先使用工具测试接口:

再调用获取数据接口

工具测试通过。再来使用wrk进行下压力测试

先看测试脚本

-- 当前是否登录的标识loginflag = falsepath = "http://192.168.3.107:8080/demo/login"-- cookie的存储信息sessionCookie = nil-- 标识当前请求为json格式wrk.headers["Content-Type"]="application/json"-- 当前的请求方法request = function()--未登录情况下,调用登录接口if loginflag == false thenuser = '{"data":'..math.random(1,3000000)..',"name":"name"}'return wrk.format('POST',path,nil,user)--已经登录则调有压力测试elsereturn wrk.format('GET',path,nil,nil)endend-- 响应处理response = function(status, headers, body)-- 首次检查if loginflag == false and status == 200 then-- 取出cookiesessionCookie = headers["Set-Cookie"]-- 存储到header头中wrk.headers["Cookie"] = sessionCookie-- 个性当前的路径path = "http://192.168.3.107:8080/demo/getUser"-- 标识当前已经登录loginflag = trueendend

执行压力测试

[root@standalone lua]# wrk -t1 -c4 -d10s --latency -s loginGet.lua http://192.168.3.107:8080/Running 10s test @ http://192.168.3.107:8080/1 threads and 4 connectionsThread Stats AvgStdevMax +/- StdevLatency 497.88us 317.38us 11.69ms 96.91%Req/Sec7.90k1.10k 8.95k 95.00%Latency Distribution50% 445.00us75% 506.00us90% 592.00us99% 1.65ms78557 requests in 10.00s, 11.10MB readRequests/sec: 7854.57Transfer/sec:1.11MB[root@standalone lua]# wrk -t1 -c8 -d10s --latency -s loginGet.lua http://192.168.3.107:8080/Running 10s test @ http://192.168.3.107:8080/1 threads and 8 connectionsThread Stats AvgStdevMax +/- StdevLatency 695.02us 325.27us 12.41ms 95.00%Req/Sec 10.18k1.12k 11.13k 90.10%Latency Distribution50% 653.00us75% 741.00us90% 0.86ms99% 1.90ms102359 requests in 10.10s, 14.56MB readRequests/sec: 10134.48Transfer/sec:1.44MB[root@standalone lua]# wrk -t2 -c8 -d10s --latency -s loginGet.lua http://192.168.3.107:8080/Running 10s test @ http://192.168.3.107:8080/2 threads and 8 connectionsThread Stats AvgStdevMax +/- StdevLatency 666.40us 224.39us 15.17ms 89.65%Req/Sec5.41k 550.216.32k 49.01%Latency Distribution50% 625.00us75% 728.00us90% 0.86ms99% 1.37ms108752 requests in 10.10s, 15.47MB readRequests/sec: 10767.26Transfer/sec:1.53MB[root@standalone lua]#

8. 总结

本文中,我将我学习到的如何通过wrk这个工具进行http的压力测试的一些方法进行了总结,并详细讲解了在linux下安装wrk的方法,相关的lua函数说明,使用了3个案例,以及通过lua脚本来定制请求信息。希望读完本文对,你有所帮助。

9. 参考文档

/wg/wrk/quanxiaoha/p/10661650.html/blog/zjumty-2221040/xinzhao/p/6233009.html/lua/lua-tutorial.html

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。