引言: 互联网服务压测是非常重要的评价方法,ab,webbench,jmeter等都是业界流行的测试工具,ab和webbench作为shell模式下轻量级的测试工具,jmeter则作为有GUI界面的更高级测试工具,各有特点,ab比webbench功能更多一些,所以这里选择ab和jmeter来做一个对比。
【测试环境的安装】
【ab】
ab就是Apache Benchmark的缩写,顾名思义它是Apache组织开发的一款web压力测试工具,优点是使用方便,统计功能强大。
ab作为一款非常流行的压测工具,使用细节这里就不多介绍了,直接给出个人的使用体会:
首先是安装,ubuntu和centos目前都提供自动安装命令 (至少ubuntu 14, centos 6可以)
ubuntu:sudo apt-get install apache2-utils
centos:yum install httpd-tools
安装好之后就可以开始进行测试。
ab一般常用参数就是 -n, -t ,和 -c。
-c(concurrency)表示用多少并发来进行测试;
-t表示测试持续多长时间;
-n表示要发送多少次测试请求。
一般-t或者-n选一个用。
对于模拟GET请求进行测试,ab非常简单,就是:ab -n 100 -c 10 'http://testurl.com/xxxx?para1=aaa¶2=bbb'
对于模拟POST请求进行测试,则稍微复杂些,需要把将要post的数据(一般是json格式)放在文件里。比如一个post接口需要如下方式访问
curl -H 'Content-Type:application/json' -X POST -d '{"actionType":"collect","appId":1,"contentId":"1770730744","contentType":"musictrack","did":"866479025346031","endType":"mobile","recommendId":"104169490_1_0_1434453099#1770730744#musictrack#USER_TO_SONG_TO_SONGS#gsql_similarity_content2content","tabId":0,"uid":"104169490"}' http://localhost:8083/query/leui/v0/post/user/behavior/content
需要吧-d 后面的json数据放在一个文件里,比如建立一个文件post_data.txt,放入:
{"actionType":"collect","appId":1,"contentId":"1770730744","contentType":"musictrack","did":"866479025346031","endType":"mobile","recommendId":"104169490_1_0_1434453099#1770730744#musictrack#USER_TO_SONG_TO_SONGS#gsql_similarity_content2content","tabId":0,"uid":"104169490"}
然后用-p参数解析并发送这个json数据:ab -n 100 -c 10 -p post_data.txt -T 'application/json' http://localhost:8083/query/leui/v0/post/user/behavior/content
【Jmeter】
jmeter是一个非常强大和用户友好的GUI工具,http访问的参数设置基本应有尽有,软件的help里的用户手册图例比较丰富,对于初学者来说很好上手
对于http测试的可配置参数有(1)http请求配置:测试目标host,端口,url路径,http请求参数,post的数据,http header(2)测试全局策略:测试发送的并发量,测试循环次数(jmeter没有测试时间的设定,只有不断发送测试请求反复重复多少次loop,或者无限重复)。对于(1)里每个可配置的参数都可以用变量${varaible_name}来代替,而araiable可以来自CSV格式的外部输入,GUI有“测试计划(test plan)右键点击-----添加-----配置元件-----CSV Data Set Config 里可以设置CSV 文件来源和CSV里每列数据对应的变量名称。
上面说的功能还有其他强大功能设置,在help文档和很多网上资料里都有详细介绍,比如CSV输入设置(博客),这里不再赘述。
一般来说,主要用到以下设置界面
新建测试计划(Test Plan)
Test Plan ---- 新建 Thread Group(线程组)
线程组 ---- 配置元件----HTTP Header Manager
线程组-----配置元件---CSV Data Set Config
线程组---sampler(采样器) -----HTTP 请求, 这里面有两个tab,一个是“parameters“ tab, 配置http请求参数,一个是“post data” tab,可配置post的数据,一般是一个json串,json串里的字段都可以用${xxx}这样的变量来表示。
这几个界面配置好即可,而且jmeter的配置保存时会生成.jmx文件,这个不只是用来保存修改配置用,而且还有一个更大的用处,就是在非GUI(命令行,shell)下运行。
因为我们的压测环境往往是linux系统,而且为了最大程度的发挥压测工具的性能,不论系统还是压测工具都最好运行在非GUI模式
linuxshell下,因为jmeter是java开发的,无需安装,只需要把jmeter解压后,在解压路径下,运行
{jmeter_install_dir)/}bin/jmeter -n -t $target -l xxxx.jtl
-n 就是静默模;
-t 后面就跟.jmx配置文件的路径;
-l 跟一个输出文件用于记录每次请求的时间,可以用jmeter GUI打开生成最终统计聚合报告。
在命令行模式下运行jmeter,还可以从命令行(shell)输入参数,只要在jmeter命令后的参数列表里加上 -JXXXX = value , XXXX被jmeter识别为一个外部输入变量,其值是value, 在jmerter配置里用${__P(XXXX)}来使用这个外部输入变量,注意"__P"开头是连着的两个下划线。
【测试构建和效果对比】
下面我们用一个实际的例子来进行ab和jmeter压力测试的效果对比, 首先是GET请求。
【ab】
先用10个并发压测100秒。
]# ab -t 100 -c 10 'http://localhost:8083/xxxx?uid=1233435&did=123456789&appId=1'
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking xxx.xxx.xxx.xxx (be patient)
Finished 733 requests
Server Software: CppCMS-Embedded/1.0.4
Server Hostname: xxx.xxx.xxx.xxx
Server Port: 8083
Document Path: / xxx?uid=79057533&did=123456789&appId=1
Document Length: 4601 bytes
Concurrency Level: 10
Time taken for tests: 100.137 seconds
Complete requests: 733
Failed requests: 732
(Connect: 0, Receive: 0, Length: 732, Exceptions: 0)
Write errors: 0
Total transferred: 3672653 bytes
HTML transferred: 3572232 bytes
Requests per second: 7.32 [#/sec] (mean)
Time per request: 1366.124 [ms] (mean)
Time per request: 136.612 [ms] (mean, across all concurrent requests)
Transfer rate: 35.82 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 2.4 2 40
Processing: 342 1352 636.3 1183 6046
Waiting: 342 1351 636.2 1183 6046
Total: 345 1354 636.8 1186 6049
Percentage of the requests served within a certain time (ms)
50% 1185
66% 1333
75% 1460
80% 1564
90% 1835
95% 2357
98% 3248
99% 5205
100% 6049 (longest request)
【jmeter】
再用jemeter以同样的配置(Thread数 为10, ramp时间为1秒,超时阈值为3000ms)
运行结果如下:
Creating summariser <summary>
Created the tree successfully using music_api_uid.jmx
Starting the test @ Thu Nov 19 11:19:43 CST 2015 (1447903183454)
Waiting for possible shutdown message on port 4445
summary + 90 in 16s = 5.7/s Avg: 1677 Min: 959 Max: 3757 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary + 202 in 31.1s = 6.5/s Avg: 1477 Min: 912 Max: 2727 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 292 in 46s = 6.4/s Avg: 1539 Min: 912 Max: 3757 Err: 0 (0.00%)
summary + 164 in 31s = 5.3/s Avg: 1830 Min: 972 Max: 5009 Err: 5 (3.05%) Active: 10 Started: 10 Finished: 0
summary = 456 in 76s = 6.0/s Avg: 1643 Min: 912 Max: 5009 Err: 5 (1.10
最终通过GUI打开请求详细记录,生成聚合报告的结果为
samples: 576
average: 1713
median: 1496
90% Line: 2353
min: 912
max: 5009
throught: 5.8/sec
kb/sec: 27.8
error%: 2.08%
ab | jmeter | |
发送总请求数 | 733 | 576 |
平均请求时间(ms) | 1366 | 1713 |
请求时间中位数(50%<)(ms) | 1185 | 1496 |
请求时间90%< (ms) | 1835 | 2353 |
error | 2.08% | |
QPS | 7.32 | 6 |
对比两次测试,ab完成了733次,而jmeter完成了576次而ab完成了733次,其实这个数据不算准确,因为jmeter不支持精确的测试时间的限制,所以我是按时强制终止了jemeter,所以有些请求可能就被漏掉了。不过我后来测试了同样总请求数时(ab用-n设置,jmeter则用 thread*loops来设置),jmeter也比ab慢戈15%,可能和jmeter自己要做很多统计有关系。
因为测试时间不是严格相等,所以主要看平均:时间分布,ab普遍低一些。双方测试环境和测试参数都一致,不知道是不是jmeter在计算返回时间上算法不一样。平均时间,jmeter统计口径也是偏高
我留了个心眼,查询了web接口后台日志,确保了两次测试的传参是一样的,那么结果的差别只能理解为两个软件在统计口径(比如返回时件的测量标准上),以及http访问方式上有差别( 比如同样是设置10个并发,一般是理解为开10个线程去不断的请求接口,但线程的调度策略不一样,对服务器的压力不一样,返回的性能也不一样)。
GET测试对比完 , 再来对比一下POST API测试的效果:
【ab】:
#ab -t 100 -c 10 -p post_data.txt -T 'application/json' http://localhost:8083/xxxxx
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking xxx.xxx.xxx.xxx (be patient)
Completed 5000 requests
Completed 10000 requests
Finished 12937 requests
Server Software: CppCMS-Embedded/1.0.4
Server Hostname: xxx.xxx.xxx.xxx
Server Port: 8083
Document Path: /xxxxx
Document Length: 92 bytes
Concurrency Level: 10
Time taken for tests: 100.001 seconds
Complete requests: 12937
Failed requests: 0
Write errors: 0
Total transferred: 2962573 bytes
Total POSTed: 4828858
HTML transferred: 1190204 bytes
Requests per second: 129.37 [#/sec] (mean)
Time per request: 77.299 [ms] (mean)
Time per request: 7.730 [ms] (mean, across all concurrent requests)
Transfer rate: 28.93 [Kbytes/sec] received
47.16 kb/s sent
76.09 kb/s total
Connection Times (ms)
min mean[+/-sd] median max
Connect: 1 2 8.9 1 1001
Processing: 31 76 78.5 69 2452
Waiting: 31 75 77.7 69 2452
Total: 33 77 79.0 71 2454
Percentage of the requests served within a certain time (ms)
50% 71
66% 80
75% 88
80% 91
90% 101
95% 113
98% 124
99% 140
100% 2454 (longest request)
【jmeter】
而同样参数配置的jmeter的结果为:
#../apache-jmeter-2.11/bin/jmeter -n -t post.jmx -JCSV=post_paras.txt -JIP=xxx.xxx.xxx.xxx -JPORT=8083 -JTHREAD=10 -JRAMP=1 -l "post_test.log"
Creating summariser <summary>
Created the tree successfully using post_to_recommend_user_action_server.jmx
Starting the test @ Tue Nov 17 20:49:37 CST 2015 (1447764577991)
Waiting for possible shutdown message on port 4445
summary + 3978 in 21.1s = 188.5/s Avg: 51 Min: 32 Max: 1049 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary + 3796 in 30.1s = 126.2/s Avg: 78 Min: 34 Max: 1596 Err: 0 (0.00%) Active: 10 Started: 10 Finished: 0
summary = 7774 in 51.1s = 152.1/s Avg: 64 Min: 32 Max: 1596 Err: 0 (0.00%)
summary + 3273 in 30.1s = 108.8/s Avg: 91 Min: 37 Max: 3091 Err: 1 (0.03%) Active: 10 Started: 10 Finished: 0
summary = 11047 in 81.1s = 136.2/s Avg: 72 Min: 32 Max: 3091 Err: 1 (0.01%)
对post_test.log进行聚合报告分析
samples: 11899
average: 58
median: 52
90% line: 76
min: 27
max: 3091
error: 0.01%
throughout: 7.6/sec
kb/sec: 1.9
ab | jmeter | |
完成请求数 | 12937 | 11899 |
平均返回时间(ms) | 77 | 58 |
最大返回时间(ms) | 3091 | |
最小返回时间(ms) | 27 | |
请求时间中位数(50%<) | 71 | 52 |
90%的请求反水时间低于(ms) | 101 | 76 |
错误率(基本是超时) | 0 | 0.01% |
QPS | 129 | 136 |
【使用对比总结】
个人体会是:
统计效果上,ab占优:ab的优点是统计的结果可读性更强更能帮助人分析,至于一些参数的差异,主要看源代码实现了,但误差在可接受的范围内,作为压力测试,我们需要的是服务器面对压力的一个大致的能力和随着压力增大后服务器性能的变化趋势,所以ab和jmeter两个数字谁更精确是没太多意义的,反而是他俩数字差别不大就已经起到了互相印证的作用。
压测方案指定上,jmeter占优:主要是jmeter支持可变参数和CSV数据集的输入,能设定更复杂的测试样例,适用范围更广。
ab不需要写配置文件,只需要几个命令行参数就能执行压测,适用于接口简单业务逻辑简单的http服务的测试。