引言: 網際網路服務壓測是非常重要的評價方法,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&para2=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%

GET API壓測結果對比
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

post api 壓測結果對比
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服務的測試。