本文介紹壓測是什麼,解釋壓測的專屬名詞,教你們如何壓測。介紹市面上的常見壓測工具(ab、locust、Jmeter、go實現的壓測工具、雲壓測),對比這些壓測工具,教你們如何選擇一款適合本身的壓測工具,本文還有兩個壓測實戰項目:html
一、項目說明python
二、壓測linux
2.3 壓測名詞解釋ios
三、常見的壓測工具git
3.4 雲壓測github
四、go-stress-testing go語言實現的壓測工具golang
五、壓測工具的比較web
六、單臺機器100w鏈接壓測實戰chrome
go 實現的壓測工具,每一個用戶用一個協程的方式模擬,最大限度的利用CPU資源數據庫
參數說明:
-c
表示併發數
-n
每一個併發執行請求的次數,總請求的次數 = 併發數 * 每一個併發執行請求的次數
-u
須要壓測的地址
# clone 項目 git clone https://github.com/link1st/go-stress-testing.git # 進入項目目錄 cd go-stress-testing # 運行 go run main.go -c 1 -n 100 -u https://www.baidu.com/
執行之後,終端每秒鐘都會輸出一次結果,壓測完成之後輸出執行的壓測結果
壓測結果展現:
─────┬───────┬───────┬───────┬────────┬────────┬────────┬────────┬──────── 耗時│ 併發數 │ 成功數│ 失敗數 │ qps │最長耗時 │最短耗時│平均耗時 │ 錯誤碼 ─────┼───────┼───────┼───────┼────────┼────────┼────────┼────────┼──────── 1s│ 1│ 8│ 0│ 8.09│ 133.16│ 110.98│ 123.56│200:8 2s│ 1│ 15│ 0│ 8.02│ 138.74│ 110.98│ 124.61│200:15 3s│ 1│ 23│ 0│ 7.80│ 220.43│ 110.98│ 128.18│200:23 4s│ 1│ 31│ 0│ 7.83│ 220.43│ 110.23│ 127.67│200:31 5s│ 1│ 39│ 0│ 7.81│ 220.43│ 110.23│ 128.03│200:39 6s│ 1│ 46│ 0│ 7.72│ 220.43│ 110.23│ 129.59│200:46 7s│ 1│ 54│ 0│ 7.79│ 220.43│ 110.23│ 128.42│200:54 8s│ 1│ 62│ 0│ 7.81│ 220.43│ 110.23│ 128.09│200:62 9s│ 1│ 70│ 0│ 7.79│ 220.43│ 110.23│ 128.33│200:70 10s│ 1│ 78│ 0│ 7.82│ 220.43│ 106.47│ 127.85│200:78 11s│ 1│ 84│ 0│ 7.64│ 371.02│ 106.47│ 130.96│200:84 12s│ 1│ 91│ 0│ 7.63│ 371.02│ 106.47│ 131.02│200:91 13s│ 1│ 99│ 0│ 7.66│ 371.02│ 106.47│ 130.54│200:99 13s│ 1│ 100│ 0│ 7.66│ 371.02│ 106.47│ 130.52│200:100 ************************* 結果 stat **************************** 處理協程數量: 1 請求總數: 100 總請求時間: 13.055 秒 successNum: 100 failureNum: 0 ************************* 結果 end ****************************
參數解釋:
耗時: 程序運行耗時。程序每秒鐘輸出一次壓測結果
併發數: 併發數,啓動的協程數
成功數: 壓測中,請求成功的數量
失敗數: 壓測中,請求失敗的數量
qps: 當前壓測的QPS(每秒鐘處理請求數量)
最長耗時: 壓測中,單個請求最長的響應時長
最短耗時: 壓測中,單個請求最短的響應時長
平均耗時: 壓測中,單個請求平均的響應時長
錯誤碼: 壓測中,接口返回的 code碼:返回次數的集合
壓測,即壓力測試,是確立系統穩定性的一種測試方法,一般在系統正常運做範圍以外進行,以考察其功能極限和隱患。
主要檢測服務器的承受能力,包括用戶承受能力(多少用戶同時玩基本不影響質量)、流量承受等。
壓測類型 | 解釋 |
---|---|
壓力測試(Stress Testing) | 也稱之爲強度測試,測試一個系統的最大抗壓能力,在強負載(大數據、高併發)的狀況下,測試系統所能承受的最大壓力,預估系統的瓶頸 |
併發測試(Concurrency Testing) | 經過模擬不少用戶同一時刻訪問系統或對系統某一個功能進行操做,來測試系統的性能,從中發現問題(併發讀寫、線程控制、資源爭搶) |
耐久性測試(Configuration Testing) | 經過對系統在大負荷的條件下長時間運行,測試系統、機器的長時間運行下的情況,從中發現問題(內存泄漏、數據庫鏈接池不釋放、資源不回收) |
壓測名詞 | 解釋 |
---|---|
併發(Concurrency) | 指一個處理器同時處理多個任務的能力(邏輯上處理的能力) |
並行(Parallel) | 多個處理器或者是多核的處理器同時處理多個不一樣的任務(物理上同時執行) |
QPS(每秒鐘查詢數量 Query Per Second) | 服務器每秒鐘處理請求數量 (req/sec 請求數/秒 一段時間內總請求數/請求時間) |
事務(Transactions) | 是用戶一次或者是幾回請求的集合 |
TPS(每秒鐘處理事務數量 Transaction Per Second) | 服務器每秒鐘處理事務數量(一個事務可能包括多個請求) |
請求成功數(Request Success Number) | 在一次壓測中,請求成功的數量 |
請求失敗數(Request Failures Number) | 在一次壓測中,請求失敗的數量 |
錯誤率(Error Rate) | 在壓測中,請求成功的數量與請求失敗數量的比率 |
最大響應時間(Max Response Time) | 在一次事務中,從發出請求或指令系統作出的反映(響應)的最大時間 |
最少響應時間(Mininum Response Time) | 在一次事務中,從發出請求或指令系統作出的反映(響應)的最少時間 |
平均響應時間(Average Response Time) | 在一次事務中,從發出請求或指令系統作出的反映(響應)的平均時間 |
機器性能 | 解釋 |
---|---|
CUP利用率(CPU Usage) | CUP 利用率分用戶態、系統態和空閒態,CPU利用率是指:CPU執行非系統空閒進程的時間與CPU總執行時間的比率 |
內存使用率(Memory usage) | 內存使用率指的是此進程所開銷的內存。 |
IO(Disk input/ output) | 磁盤的讀寫包速率 |
網卡負載(Network Load) | 網卡的進出帶寬,包量 |
訪問 | 解釋 |
---|---|
PV(頁面瀏覽量 Page View) | 用戶每打開1個網站頁面,記錄1個PV。用戶屢次打開同一頁面,PV值累計屢次 |
UV(網站獨立訪客 Unique Visitor) | 經過互聯網訪問、流量網站的天然人。1天內相同訪客屢次訪問網站,只計算爲1個獨立訪客 |
( 30000000*0.8 ) / (86400 * 0.2) ≈ 1389 (QPS)
1389 / 69 ≈ 20
ApacheBench 是 Apache服務器自帶的一個web壓力測試工具,簡稱ab。ab又是一個命令行工具,對發起負載的本機要求很低,根據ab命令能夠建立不少的併發訪問線程,模擬多個訪問者同時對某一URL地址進行訪問,所以能夠用來測試目標服務器的負載壓力。總的來講ab工具小巧簡單,上手學習較快,能夠提供須要的基本性能指標,可是沒有圖形化結果,不能監控。
ab屬於一個輕量級的壓測工具,結果不會特別準確,能夠用做參考。
# 在linux環境安裝 sudo yum -y install httpd
Usage: ab [options] [http[s]://]hostname[:port]/path 用法:ab [選項] 地址 選項: Options are: -n requests #執行的請求數,即一共發起多少請求。 -c concurrency #請求併發數。 -s timeout #指定每一個請求的超時時間,默認是30秒。 -k #啓用HTTP KeepAlive功能,即在一個HTTP會話中執行多個請求。默認時,不啓用KeepAlive功能。
# 使用ab壓測工具,對百度的連接 請求100次,併發數1 ab -n 100 -c 1 https://www.baidu.com/
壓測結果
~ >ab -n 100 -c 1 https://www.baidu.com/ This is ApacheBench, Version 2.3 <$Revision: 1430300 $> Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/ Benchmarking www.baidu.com (be patient).....done Server Software: BWS/1.1 Server Hostname: www.baidu.com Server Port: 443 SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES128-GCM-SHA256,2048,128 Document Path: / Document Length: 227 bytes Concurrency Level: 1 Time taken for tests: 9.430 seconds Complete requests: 100 Failed requests: 0 Write errors: 0 Total transferred: 89300 bytes HTML transferred: 22700 bytes Requests per second: 10.60 [#/sec] (mean) Time per request: 94.301 [ms] (mean) Time per request: 94.301 [ms] (mean, across all concurrent requests) Transfer rate: 9.25 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 54 70 16.5 69 180 Processing: 18 24 12.0 23 140 Waiting: 18 24 12.0 23 139 Total: 72 94 20.5 93 203 Percentage of the requests served within a certain time (ms) 50% 93 66% 99 75% 101 80% 102 90% 108 95% 122 98% 196 99% 203 100% 203 (longest request)
Concurrency Level
併發請求數Time taken for tests
整個測試時間Complete requests
完成請求個數Failed requests
失敗個數Requests per second
吞吐量,指的是某個併發用戶下單位時間內處理的請求數。等效於QPS,其實能夠看做同一個統計方式,只是叫法不一樣而已。Time per request
用戶平均請求等待時間Time per request
服務器處理時間是很是簡單易用、分佈式、python開發的壓力測試工具。有圖形化界面,支持將壓測數據導出。
# pip3 安裝locust pip3 install locust # 查看是否安裝成功 locust -h # 運行 Locust 分佈在多個進程/機器庫 pip3 install pyzmq # webSocket 壓測庫 pip3 install websocket-client
編寫壓測腳本 test.py
from locust import HttpLocust, TaskSet, task # 定義用戶行爲 class UserBehavior(TaskSet): @task def baidu_index(self): self.client.get("/") class WebsiteUser(HttpLocust): task_set = UserBehavior # 指向一個定義的用戶行爲類 min_wait = 3000 # 執行事務之間用戶等待時間的下界(單位:毫秒) max_wait = 6000 # 執行事務之間用戶等待時間的上界(單位:毫秒)
locust -f test.py --host=https://www.baidu.com
訪問 http://localhost:8089 進入壓測首頁
Number of users to simulate 模擬用戶數
Hatch rate (users spawned/second) 每秒鐘增長用戶數
點擊 "Start swarming" 進入壓測頁面
壓測界面右上角有:被壓測的地址、當前狀態、RPS、失敗率、開始或重啓按鈕
性能測試參數
Type
請求的類型,例如GET/POSTName
請求的路徑Request
當前請求的數量Fails
當前請求失敗的數量Median
中間值,單位毫秒,請求響應時間的中間值Average
平均值,單位毫秒,請求的平均響應時間Min
請求的最小服務器響應時間,單位毫秒Max
請求的最大服務器響應時間,單位毫秒Average size
單個請求的大小,單位字節Current RPS
表明吞吐量(Requests Per Second的縮寫),指的是某個併發用戶數下單位時間內處理的請求數。等效於QPS,其實能夠看做同一個統計方式,只是叫法不一樣而已。
Apache JMeter是Apache組織開發的基於Java的壓力測試工具。用於對軟件作壓力測試,它最初被設計用於Web應用測試,但後來擴展到其餘測試領域。
JMeter可以對應用程序作功能/迴歸測試,經過建立帶有斷言的腳原本驗證你的程序返回了你指望的結果。
訪問 https://jmeter-plugins.org/in... 下載解壓之後便可使用
JMeter的功能過於強大,這裏暫時不介紹用法,能夠查詢相關文檔使用(參考文獻中有推薦的教程文檔)
顧名思義就是將壓測腳本部署在雲端,經過雲端對對咱們的應用進行全方位壓測,只須要配置壓測的參數,無需準備實體機,雲端自動給咱們分配須要壓測的雲主機,對被壓測目標進行壓測。
雲壓測的優點:
固然了雲壓測是一款商業產品,在使用的時候天然仍是須要收費的,並且價格仍是比較昂貴的~
PTS(Performance Testing Service)是面向全部技術背景人員的雲化測試工具。有別於傳統工具的繁複,PTS以互聯網化的交互,提供性能測試、API調試和監測等多種能力。自研和適配開源的功能均可以輕鬆模擬任意體量的用戶訪問業務的場景,任務隨時發起,免去繁瑣的搭建和維護成本。更是緊密結合監控、流控等兄弟產品提供一站式高可用能力,高效檢驗和管理業務性能。
阿里雲一樣仍是支持滲透測試,經過模擬黑客對業務系統進行全面深刻的安全測試。
經過建立虛擬機器人模擬多用戶的併發場景,提供一整套完整的服務器壓測解決方案
Usage of ./go_stress_testing_mac: -c uint 併發數 (default 1) -d string 調試模式 (default "false") -n uint 請求總數 (default 1) -p string curl文件路徑 -u string 請求地址 -v string 驗證方法 http 支持:statusCode、json webSocket支持:json (default "statusCode")
-n
是單個用戶請求的次數,請求總次數 = -c
* -n
, 這裏考慮的是模擬用戶行爲,因此這個是每一個用戶請求的次數# 查看用法 go run main.go # 使用請求百度頁面 go run main.go -c 1 -n 100 -u https://www.baidu.com/ # 使用debug模式請求百度頁面 go run main.go -c 1 -n 1 -d true -u https://www.baidu.com/ # 使用 curl文件(文件在curl目錄下) 的方式請求 go run main.go -c 1 -n 1 -p curl/baidu.curl.txt # 壓測webSocket鏈接 go run main.go -c 10 -n 10 -u ws://127.0.0.1:8089/acc
curl是Linux在命令行下的工做的文件傳輸工具,是一款很強大的http命令行工具。
使用curl文件能夠壓測使用非GET的請求,支持設置http請求的 method、cookies、header、body等參數
chrome 瀏覽器生成 curl文件,打開開發者模式(快捷鍵F12),如圖所示,生成 curl 在終端執行命令
生成內容粘貼到項目目錄下的curl/baidu.curl.txt文件中,執行下面命令就能夠從curl.txt文件中讀取須要壓測的內容進行壓測了
# 使用 curl文件(文件在curl目錄下) 的方式請求 go run main.go -c 1 -n 1 -p curl/baidu.curl.txt
|____main.go // main函數,獲取命令行參數 |____server // 處理程序目錄 | |____dispose.go // 壓測啓動,註冊驗證器、啓動統計函數、啓動協程進行壓測 | |____statistics // 統計目錄 | | |____statistics.go // 接收壓測統計結果並處理 | |____golink // 創建鏈接目錄 | | |____http_link.go // http創建鏈接 | | |____websocket_link.go // webSocket創建鏈接 | |____client // 請求數據客戶端目錄 | | |____http_client.go // http客戶端 | | |____websocket_client.go // webSocket客戶端 | |____verify // 對返回數據校驗目錄 | | |____http_verify.go // http返回數據校驗 | | |____websokcet_verify.go // webSocket返回數據校驗 |____heper // 通用函數目錄 | |____heper.go // 通用函數 |____model // 模型目錄 | |____request_model.go // 請求數據模型 | |____curl_model.go // curl文件解析 |____vendor // 項目依賴目錄
這裏使用go-stress-testing對go server進行壓測(部署在同一臺機器上),並統計壓測結果
CPU: 4核 (Intel Xeon(Cascade Lake) Platinum 8269 2.5 GHz/3.2 GHz)
內存: 16G
硬盤: 20G SSD
系統: CentOS 7.6
go version: go1.12.9 linux/amd64
package main import ( "log" "net/http" ) const ( httpPort = "8088" ) func main() { runtime.GOMAXPROCS(runtime.NumCPU() - 1) hello := func(w http.ResponseWriter, req *http.Request) { data := "Hello, World!" w.Header().Add("Server", "golang") w.Write([]byte(data)) return } http.HandleFunc("/", hello) err := http.ListenAndServe(":"+httpPort, nil) if err != nil { log.Fatal("ListenAndServe: ", err) } }
./go_stress_testing_linux -c 100 -n 10000 -u http://127.0.0.1:8088/
併發數 | go_stress_testing QPS |
---|---|
1 | 6394.86 |
4 | 16909.36 |
10 | 18456.81 |
20 | 19490.50 |
30 | 19947.47 |
50 | 19922.56 |
80 | 19155.33 |
100 | 18336.46 |
200 | 16813.86 |
從壓測的結果上看:效果還不錯,壓測QPS有接近2W
- | ab | locust | Jmeter | go-stress-testing | 雲壓測 |
---|---|---|---|---|---|
實現語言 | C | Python | Java | Golang | - |
UI界面 | 無 | 有 | 有 | 無 | 無 |
優點 | 使用簡單,上手簡單 | 支持分佈式、壓測數據支持導出 | 插件豐富,支持生成HTML報告 | 項目開源,使用簡單,沒有依賴,支持webSocket壓測 | 更加真實的模擬用戶,支持更高的壓測力度 |
這個世界上沒有最好的,只有最適合的,工具千千萬,選擇一款適合你的纔是最重要的
在實際使用中有各類場景,選擇工具的時候就須要考慮這些:
以前寫了一篇文章,基於websocket單臺機器支持百萬鏈接分佈式聊天(IM)系統(不瞭解這個項目能夠查看上一篇或搜索一下文章),這裏咱們要實現單臺機器支持100W鏈接的壓測
目標:
說明:
gowebsocket 分佈式聊天(IM)系統:
因爲本身手上沒有本身的服務器,因此須要臨時購買的雲服務器
壓測服務器:
16臺(稍後解釋爲何須要16臺機器)
CPU: 2核
內存: 8G
硬盤: 20G
系統: CentOS 7.6
被壓測服務:
1臺
CPU: 4核
內存: 32G
硬盤: 20G SSD
系統: CentOS 7.6
被壓測服務器須要保持100W長鏈接,客戶和服務器端是經過socket通信的,每一個鏈接須要創建一個socket,程序須要保持100W長鏈接就須要單個程序能打開100W個文件句柄
# 查看系統默認的值 ulimit -n # 設置最大打開文件數 ulimit -n 1040000
這裏設置的要超過100W,程序除了有100W鏈接還有其它資源鏈接(數據庫、資源等鏈接),這裏設置爲 104W
centOS 7.6 上述設置不生效,須要手動修改配置文件
vim /etc/security/limits.conf
這裏須要把硬限制和軟限制、root用戶和全部用戶都設置爲 1040000
core 是限制內核文件的大小,這裏設置爲 unlimited
# 添加一下參數 root soft nofile 1040000 root hard nofile 1040000 root soft nofile 1040000 root hard nproc 1040000 root soft core unlimited root hard core unlimited * soft nofile 1040000 * hard nofile 1040000 * soft nofile 1040000 * hard nproc 1040000 * soft core unlimited * hard core unlimited
注意:
/proc/sys/fs/file-max
表示系統級別的可以打開的文件句柄的數量,不能小於limits中設置的值
若是file-max的值小於limits設置的值會致使系統重啓之後沒法登陸
# file-max 設置的值參考 cat /proc/sys/fs/file-max 12553500
修改之後重啓服務器,ulimit -n
查看配置是否生效
因爲linux端口的範圍是 0~65535(2^16-1)
這個和操做系統無關,無論linux是32位的仍是64位的
這個數字是因爲tcp協議決定的,tcp協議頭部表示端口只有16位,因此最大值只有65535(若是每臺機器多幾個虛擬ip就能突破這個限制)
1024如下是系統保留端口,因此能使用的1024到65535
若是須要100W長鏈接,每臺機器有 65535-1024 個端口, 100W / (65535-1024) ≈ 15.5,因此這裏須要16臺服務器
vim /etc/sysctl.conf
在文件末尾添加net.ipv4.ip_local_port_range = 1024 65000 net.ipv4.tcp_mem = 786432 2097152 3145728 net.ipv4.tcp_rmem = 4096 4096 16777216 net.ipv4.tcp_wmem = 4096 4096 16777216
配置解釋:
ip_local_port_range
表示TCP/UDP協議容許使用的本地端口號 範圍:1024~65000tcp_mem
肯定TCP棧應該如何反映內存使用,每一個值的單位都是內存頁(一般是4KB)。第一個值是內存使用的下限;第二個值是內存壓力模式開始對緩衝區使用應用壓力的上限;第三個值是內存使用的上限。在這個層次上能夠將報文丟棄,從而減小對內存的使用。對於較大的BDP能夠增大這些值(注意,其單位是內存頁而不是字節)tcp_rmem
爲自動調優定義socket使用的內存。第一個值是爲socket接收緩衝區分配的最少字節數;第二個值是默認值(該值會被rmem_default覆蓋),緩衝區在系統負載不重的狀況下能夠增加到這個值;第三個值是接收緩衝區空間的最大字節數(該值會被rmem_max覆蓋)。tcp_wmem
爲自動調優定義socket使用的內存。第一個值是爲socket發送緩衝區分配的最少字節數;第二個值是默認值(該值會被wmem_default覆蓋),緩衝區在系統負載不重的狀況下能夠增加到這個值;第三個值是發送緩衝區空間的最大字節數(該值會被wmem_max覆蓋)。
./go_stress_testing_linux -c 62500 -n 1 -u ws://192.168.0.74:443/acc
62500*16 = 100W
正好能夠達到咱們的要求
創建鏈接之後,-n 1
發送一個ping的消息給服務器,收到響應之後保持鏈接不中斷
# linux 命令 ps # 查看進程內存、cup使用狀況 iostat # 查看系統IO狀況 nload # 查看網絡流量狀況 /proc/pid/status # 查看進程狀態
查看goWebSocket鏈接數統計,能夠看到 clientsLen鏈接數爲100W,goroutine數量2000008個,每一個鏈接兩個goroutine加上項目啓動默認的8個。這裏能夠看到鏈接數知足了100W
從壓測服務上查看鏈接數是否達到了要求,壓測完成的統計數據併發數爲62500,是每一個客戶端鏈接的數量,總鏈接數: 62500*16=100W
,
鏈接數 | 內存 |
---|---|
10000 | 281M |
100000 | 2.7g |
200000 | 5.4g |
500000 | 13.1g |
1000000 | 25.8g |
100W鏈接時的查看內存詳細數據:
cat /proc/pid/status VmSize: 27133804 kB
27133804/1000000≈27.1
100W鏈接,佔用了25.8g的內存,粗略計算了一下,一個鏈接佔用了27.1Kb的內存,因爲goWebSocket項目每一個用戶鏈接起了兩個協程處理用戶的讀寫事件,因此內存佔用稍微多一點
若是須要如何減小內存使用能夠參考 @Roy11568780 大佬給的解決方案
傳統的golang中是採用的一個goroutine循環read的方法對應每個socket。實際百萬鏈路場景中這是巨大的資源浪費,優化的原理也不是什麼新東西,golang中同樣也可使用epoll的,把fd拿到epoll中,檢測到事件而後在協程池裏面去讀就好了,看狀況讀寫分別10-20的協程goroutine池應該就足夠了
至此,壓測已經所有完成,單臺機器支持100W鏈接已經知足~
到這裏壓測總算完成,本次壓測花費16元鉅款。
單臺機器支持100W鏈接是實測是知足的,可是實際業務比較複雜,仍是須要持續優化~
經過實現介紹什麼是壓測,在什麼狀況下須要壓測,若是以爲現有的壓測工具不適用,能夠本身實現或者是改形成適合本身的工具。
基於websocket單臺機器支持百萬鏈接分佈式聊天(IM)系統
github 搜:link1st 查看項目 go-stress-testing