wrk,ab,locust,Jmeter 壓測結果比較


背景:

項目需要對一批接口進行壓測,要求是接口的QPS(Quest Per Second每秒請求數)達到6萬以上
由於樓主一直使用的壓力測試工具是jmeter,但是jmeter單台電腦無法達到6萬的QPS,於是使用網傳比較好用的其他性能工具進行壓測比較,選出一款符合要求的工具進行壓測。

壓測機器:Linux 4核8G
由於不同的性能工具壓測時消耗的系統資源不一樣,防止系統資源造成的干擾,測試時服務器只運行壓測工具,且非本機壓本機。

示例接口,post請求,請求body可為空
POST https://api.midukanshu.com/logstash/userbehavior/report
返回:
{"code":0,"message":"成功","currentTime":1543386393,"data":[]}

一、 Wrk

wrk是一款現代化的HTTP性能測試工具,即使運行在單核CPU上也能產生顯著的壓力。最大的優點是它支持多線程,這樣更容易發揮多核 CPU 的能力,從而更容易測試出系統的極限能力。

安裝

git clone https://github.com/wg/wrk.git
cd wrk/
make

查看版本

./wrk -v

 

 

參數說明

-c:總的連接數(每個線程處理的連接數=總連接數/線程數)
-d:測試的持續時間,如2s(2second)2m(2minute)2h(hour),默認為s
-t:需要執行的線程總數,默認為2,一般線程數不宜過多. 核數的24倍足夠了. 多了反而因為線程切換過多造成效率降低
-s:執行Lua腳本,這里寫lua腳本的路徑和名稱,后面會給出案例
-H:需要添加的頭信息,注意header的語法,舉例,-H token: abcdef
timeout:超時的時間
latency:顯示延遲統計信息

返回結果

Latency:響應時間
Req/Sec:每個線程每秒鍾的執行的連接數
Avg:平均
Max:最大
Stdev:標准差
+/- Stdev正負一個標准差占比
Requests/sec:每秒請求數(也就是QPS),等於總請求數/測試總耗時
Latency Distribution,如果命名中添加了—latency就會出現相關信息

運行

./wrk -t 5 -c 300 -d 60 --latency https://api.midukanshu.com/logstash/userbehavior/create

 


300個連接數跑60秒:Request/sec(每秒請求數):3322.48

 

./wrk -t 5 -c 500 -d 60 --latency https://api.midukanshu.com/logstash/userbehavior/create

 


500個連接數跑60秒:Request/sec(每秒請求數):3321.67

 

可見連接數從300加到500,QPS沒有明顯變化,就沒有再往上加的必要了,再加也只會花更多的時間去坐線程的切換,QPS不一定上升,而且300個連接數時CPU已經跑滿,后面會有截圖說明

如果post請求的body不為空則指定lua文件進行讀取,示例如下:
./wrk -t 5 -c 300 -d 60 --script=post.lua --latency https://api.midukanshu.com/logstash/userbehavior/create
post.lua文件內容
wrk.method = "POST"
wrk.body = ""
wrk.headers["Content-Type"] = "application/x-www-form-urlencoded"

二、 Apache Benchmark

Apache Benchmark簡稱 ab,是apache自帶的壓力測試工具

安裝:

sudo yum install httpd-tools

查看版本:

ab -V

 

 

參數說明

-n 表示請求總數(-t參數可任選其一)
-c 表示並發數
-t 標識請求時間
-p:模擬post請求,文件格式為gid=2&status=1,配合-T使用
-T:post數據所使用的Content-Type頭信息,如-T 'application/x-www-form-urlencoded'

返回結果

Server Software: nginx/1.13.6 #測試服務器的名字
Server Hostname: api.midukanshu.com #請求的URL主機名
Server Port: 443 #web服務器監聽的端口

Document Path: /logstash/userbehavior/create   #請求的URL中的根絕對路徑
Document Length: 0 bytes #HTTP響應數據的正文長度

Concurrency Level: 300        # 並發用戶數,這是我們設置的參數之一
Time taken for tests: 22.895 seconds #所有這些請求被處理完成所花費的總時間
Complete requests: 50000        # 總請求數量,這是我們設置的參數之一
Failed requests: 99         # 表示失敗的請求數量,這里的失敗是指請求在連接服務器、發送數據等環節發生異常,以及無響應后超時的情況
Write errors: 0
Total transferred: 96200 bytes    #所有請求的響應數據長度總和。包括每個HTTP響應數據的頭信息和正文數據的長度
HTML transferred: 79900 bytes    # 所有請求的響應數據中正文數據的總和,也就是減去了Total transferredHTTP響應數據中的頭信息的長度
Requests per second: 2183.91 [#/sec] (mean) #吞吐率,計算公式:Complete requests/Time taken for tests 總請求數/處理完成這些請求數所花費的時間
Time per request: 137.368 [ms] (mean) # 用戶平均請求等待時間,計算公式:Time token for tests/Complete requests/Concurrency Level)。處理完成所有請求數所花費的時間/(總請求數/並發用戶數)
Time per request: 0.458 [ms] (mean, across all concurrent requests) #服務器平均請求等待時間,計算公式:Time taken for tests/Complete requests,正好是吞吐率的倒數。也可以這么統計:Time per request/Concurrency Level
Transfer rate: 652.50 [Kbytes/sec] received #表示這些請求在單位時間內從服務器獲取的數據長度,計算公式:Total trnasferred/ Time taken for tests,這個統計很好的說明服務器的處理能力達到極限時,其出口寬帶的需求量。

運行

ab -c 300 -t 60 https://api.midukanshu.com/logstash/userbehavior/create

 

 

300線程跑60秒:Requests per second=2301.68

ab -c 500 -t 60 https://api.midukanshu.com/logstash/userbehavior/create

 

 

500線程跑60秒:Requests per second=2279.27

可見線程數加到500,還不如300的了,所以有時候線程數不是加的越高越好,更根據服務器的配置,CPU,IO,帶寬等的消耗設置合理的線程數
細心的讀者可能看出,我雖然設置了-t參數為60s,但實際只運行了20多秒,因為ab跑滿50000個request就自己停了,想跑夠60s可以使用-n參數

如果post請求的body不為空則指定文件進行讀取,示例如下:
ab -n 100 -c 10 -p 'post.txt' -T 'application/x-www-form-urlencoded' 'http://test.api.com/ttk/auth/info/'
post.txt文件內容
devices=4&status=1

三、 Locust

Locust是一個Python編寫的分布式的性能測試工具

安裝

安裝python pip
sudo yum -y install python-pip
通過Python自帶的pip安裝locust
pip install locustio

查看版本:

locust –version

 

 

參數說明

--host指定被測試的主機,采用以格式:http://192.168.21.25
-f指定運行 Locust 性能測試文件,默認為: locustfile.py
-no-web no-web 模式運行測試,需要 -c -r 配合使用
-c指定並發用戶數,作用於 no-web 模式。
-r指定每秒啟動的用戶數,作用於 no-web 模式。
-t設置運行時間, 例如: (300s, 20m, 3h, 1h30m). 作用於 no-web 模式。

返回結果

Name:請求方式,請求路徑;
reqs:當前請求的數量;
fails:當前請求失敗的數量;
Avg:所有請求的平均響應時間,毫秒;
Min:請求的最小的服務器響應時間,毫秒;
Max:請求的最大服務器響應時間,毫秒;
Median:中間值,單位毫秒;
req/s:每秒鍾請求的個數。
Total:各接口的匯總信息

運行:
Locust_demo.py文件內容

# coding=utf-8
from locust import HttpLocust, TaskSet, task
class UserBehavior(TaskSet):

@task(1)
def profile(self):
self.client.post("/logstash/userbehavior/report", {})

class WebsiteUser(HttpLocust):
task_set = UserBehavior
min_wait = 0
max_wait = 0

locust -f locust_demo.py --host=https://api.midukanshu.com --no-web -c 300 -t 60s

 


300線程跑60秒:Req/s=730.10

 

locust -f locust_demo.py --host=https://api.midukanshu.com --no-web -c 500 -t 60s

 


500線程跑60秒:Req/s=741.50

 

四、 Jmeter

Apache JMeter是Apache組織開發的基於Java的壓力測試工具

安裝

安裝jdk:yum -y list java
yum install -y java-1.8.0-openjdk-devel.x86_64
配置Java環境變量后執行java -version

 

 

下載:apache-jmeter-3.2.tgz
然后解壓到當前傳的目錄
tar zxvf apache-jmeter-3.2.tgz jmeter

查看版本:

見jmeter主目錄

參數說明:

-n : GUI 模式執行JMeter
-t : 執行測試文件所在的位置及文件名
-r : 遠程將所有agent啟動,用在分布式測試場景下,不是分布式測試只是單點就不需要-r
-l : 指定生成測試結果的保存文件, jtl 文件格式
-e : 測試結束后,生成測試報告
-o : 指定測試報告的存放位置

返回結果:

Avg:所有請求的平均響應時間,毫秒;
Min:請求的最小的服務器響應時間,毫秒;
Max:請求的最大服務器響應時間,毫秒;
Err:請求錯誤個數,錯誤百分率;
Active:激活的線程數,當Active=0,則說明運行中的線程數為0,則壓測結束。
Started:啟動的線程數
Finished:完成的線程數

運行腳本:

./jmeter.sh -n -t ./jmx/userbehavior_report.jmx
300個線程跑60秒:

 

 

Summary + 398526 in 00:00:18 =21959.8/s
Summary = 1018846 in 00:01:04 =15904.6/s
Summary =表示總共運行1分04秒,請求了1018846個接口,這1分04秒內的QPS=15904.6/s
Summary +表示統計最近18秒,請求了398526個接口,即00:00:46到00:01:04期間的18秒,QPS=21959.8/s
500個線程跑60秒:
到這差不多了,500線程跑出來也沒300的QPS高,就不放圖了

總結:
300線程跑60秒, 對比各壓測工具的 QPS:
Wrk=3322.48/s
Ab=2301.68/s
Locust= 730.10/s
Jmeter=21959.8/s
我曾以為的壓測結果是:wrk > ab > locust > jmeter
實際結果是:jmeter > wrk > ab > locust

五、資源消耗對比

Top參數解釋:

cpu狀態
6.7% us 用戶空間占用CPU的百分比。
0.4% sy 內核空間占用CPU的百分比。
0.0% ni 改變過優先級的進程占用CPU的百分比
92.9% id 空閑CPU百分比
0.0% wa IO等待占用CPU的百分比
0.0% hi 硬中斷(Hardware IRQ)占用CPU的百分比
0.0% si 軟中斷(Software Interrupts)占用CPU的百分比
內存狀態
8306544k total 物理內存總量(8GB
7775876k used 使用中的內存總量(7.7GB
530668k free 空閑內存總量(530M
79236k buffers 緩存的內存量 79M
各進程(任務)的狀態監控
PID 進程id
USER 進程所有者
PR 進程優先級
NI nice值。負值表示高優先級,正值表示低優先級
VIRT 進程使用的虛擬內存總量,單位kbVIRT=SWAP+RES
RES 進程使用的、未被換出的物理內存大小,單位kbRES=CODE+DATA
SHR 共享內存大小,單位kb
S 進程狀態。D=不可中斷的睡眠狀態 R=運行 S=睡眠 T=跟蹤/停止 Z=僵屍進程
%CPU 上次更新到現在的CPU時間占用百分比
%MEM 進程使用的物理內存百分比
TIME+ 進程使用的CPU時間總計,單位1/100
COMMAND 進程名稱(命令名/命令行)

在top基本視圖中,按鍵盤數字“1”,可監控每個邏輯CPU的狀況:
可看出壓測服務器有4個邏輯CPU

 

 

300線程跑60秒CPU消耗如圖:
Wrk=377.1%
Ab=99.7%
Locust= 100%
Jmeter=396.4%
如果服務器是多核CPU可能在下方看到有些進程CPU占用超過100%,這種一般是該進程使用了多核。
可以看出wrk和jmeter都超過100%,且jmeter的396/4=99%,即使用了服務器99%的性能,
在壓力測試過程中,最好時刻留意哪些資源成為了瓶頸,比如:CPU 是不是跑滿了,IO 是不是跑滿了
查看0.0 wa這里,IO等待所占用的CPU時間的百分比,高過30%時IO壓力高。

比較結果:

工具 wrk ab locust jmeter
安裝 簡單 簡單 依賴python 依賴jdk
場景壓測 不支持 不支持 支持 支持
UI界面
腳本錄制 利用本地ProxyServer或badboy
資源監控 通過JMeterPlugins插件和ServerAgent實現
報告分析 生成HTML報告

雖然jmeter提供UI界面,但是其壓測腳本也依賴UI界面,導致其無法在Linux服務器上直接編輯寫腳本,只有編寫好腳本后再傳到Linux服務器。
關於對於壓測工具的選擇

如果你想做場景的壓測,而不是單個接口的壓測
可使用jmeter或locust,支持接口串聯,接口body參數化,思考時間等復雜場景
如果你壓測要求的並發比較高,需要使用分布式壓測
可使用jmeter或locust
如果你關注接口的返回,多維度壓測報告統計
jmeter,jmeter,jmeter
如果想盡快編寫接口,只關注接口的發送,造成的QPS和錯誤率
可使用wrk或ab
實踐中也可以選擇自己熟悉的壓測工具

由於單台4核8G服務器對待測接口最高能造成2萬的QPS,還是距離我需要的6萬還有一定距離,這時候可以使用Jmeter的分布式壓測

當然還有更多我還沒了解到的優秀壓測工具,壓測結果存在一定局限,僅供參考
歡迎交流指正,感謝閱讀。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM