本文介紹壓測是什么,解釋壓測的專屬名詞,教大家如何壓測。介紹市面上的常見壓測工具(ab、locust、Jmeter、go實現的壓測工具、云壓測),對比這些壓測工具,教大家如何選擇一款適合自己的壓測工具,本文還有兩個壓測實戰項目:
- 單臺機器對HTTP短連接 QPS 1W+ 的壓測實戰
- 單臺機器100W長連接的壓測實戰
目錄
- 1、項目說明
- 1.1 go-stress-testing
- 1.2 項目體驗
- 2、壓測
- 2.1 壓測是什么
- 2.2 為什么要壓測
- 2.3 壓測名詞解釋
- 2.3.1 壓測類型解釋
- 2.3.2 壓測名詞解釋
- 2.3.3 機器性能指標解釋
- 2.3.4 訪問指標解釋
- 3.4 如何計算壓測指標
- 3、常見的壓測工具
- 3.1 ab
- 3.2 locust
- 3.3 Jmeter
- 3.4 云壓測
- 3.4.1 云壓測介紹
- 3.4.2 阿里云 性能測試 PTS
- 3.4.3 騰訊云 壓測大師 LM
- 4、go-stress-testing go語言實現的壓測工具
- 4.1 介紹
- 4.2 用法
- 4.3 實現
- 4.4 go-stress-testing 對 Golang web 壓測
- 5、壓測工具的比較
- 5.1 比較
- 5.2 如何選擇壓測工具
- 6、單臺機器100w連接壓測實戰
- 6.1 說明
- 6.2 內核優化
- 6.3 客戶端配置
- 6.4 準備
- 6.5 壓測數據
- 7、總結
- 8、參考文獻
1、項目說明
1.1 go-stress-testing
go 實現的壓測工具,每個用戶用一個協程的方式模擬,最大限度的利用CPU資源
1.2 項目體驗
- 可以在 mac/linux/windows 不同平臺下執行的命令
參數說明:
-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碼:返回次數的集合
2、壓測
2.1 壓測是什么
壓測,即壓力測試,是確立系統穩定性的一種測試方法,通常在系統正常運作范圍之外進行,以考察其功能極限和隱患。
主要檢測服務器的承受能力,包括用戶承受能力(多少用戶同時玩基本不影響質量)、流量承受等。
2.2 為什么要壓測
- 壓測的目的就是通過壓測(模擬真實用戶的行為),測算出機器的性能(單臺機器的QPS),從而推算出系統在承受指定用戶數(100W)時,需要多少機器能支撐得住
- 壓測是在上線前為了應對未來可能達到的用戶數量的一次預估(提前演練),壓測以后通過優化程序的性能或準備充足的機器,來保證用戶的體驗。
2.3 壓測名詞解釋
2.3.1 壓測類型解釋
壓測類型 | 解釋 |
---|---|
壓力測試(Stress Testing) | 也稱之為強度測試,測試一個系統的最大抗壓能力,在強負載(大數據、高并發)的情況下,測試系統所能承受的最大壓力,預估系統的瓶頸 |
并發測試(Concurrency Testing) | 通過模擬很多用戶同一時刻訪問系統或對系統某一個功能進行操作,來測試系統的性能,從中發現問題(并發讀寫、線程控制、資源爭搶) |
耐久性測試(Configuration Testing) | 通過對系統在大負荷的條件下長時間運行,測試系統、機器的長時間運行下的狀況,從中發現問題(內存泄漏、數據庫連接池不釋放、資源不回收) |
2.3.2 壓測名詞解釋
壓測名詞 | 解釋 |
---|---|
并發(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) | 在一次事務中,從發出請求或指令系統做出的反映(響應)的平均時間 |
2.3.3 機器性能指標解釋
機器性能 | 解釋 |
---|---|
CUP利用率(CPU Usage) | CUP 利用率分用戶態、系統態和空閑態,CPU利用率是指:CPU執行非系統空閑進程的時間與CPU總執行時間的比率 |
內存使用率(Memory usage) | 內存使用率指的是此進程所開銷的內存。 |
IO(Disk input/ output) | 磁盤的讀寫包速率 |
網卡負載(Network Load) | 網卡的進出帶寬,包量 |
2.3.4 訪問指標解釋
訪問 | 解釋 |
---|---|
PV(頁面瀏覽量 Page View) | 用戶每打開1個網站頁面,記錄1個PV。用戶多次打開同一頁面,PV值累計多次 |
UV(網站獨立訪客 Unique Visitor) | 通過互聯網訪問、流量網站的自然人。1天內相同訪客多次訪問網站,只計算為1個獨立訪客 |
2.4 如何計算壓測指標
壓測我們需要有目的性的壓測,這次壓測我們需要達到什么目標(如:單臺機器的性能為100QPS?網站能同時滿足100W人同時在線)
可以通過以下計算方法來進行計算:
壓測原則:每天80%的訪問量集中在20%的時間里,這20%的時間就叫做峰值
公式: ( 總PV數80% ) / ( 每天的秒數20% ) = 峰值時間每秒鐘請求數(QPS)
機器: 峰值時間每秒鐘請求數(QPS) / 單臺機器的QPS = 需要的機器的數量
假設:網站每天的用戶數(100W),每天的用戶的訪問量約為3000W PV,這臺機器的需要多少QPS?
( 30000000*0.8 ) / (86400 * 0.2) ≈ 1389 (QPS)
- 假設:單臺機器的的QPS是69,需要需要多少臺機器來支撐?
1389 / 69 ≈ 20
3、常見的壓測工具
3.1 ab
- 簡介
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
服務器處理時間
3.2 Locust
- 簡介
是非常簡單易用、分布式、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,其實可以看作同一個統計方式,只是叫法不同而已。
3.3 Jmeter
- 簡介
Apache JMeter是Apache組織開發的基于Java的壓力測試工具。用于對軟件做壓力測試,它最初被設計用于Web應用測試,但后來擴展到其他測試領域。
JMeter能夠對應用程序做功能/回歸測試,通過創建帶有斷言的腳本來驗證你的程序返回了你期望的結果。
- 安裝
訪問 https://jmeter-plugins.org/install/Install/ 下載解壓以后即可使用
- 用法
JMeter的功能過于強大,這里暫時不介紹用法,可以查詢相關文檔使用(參考文獻中有推薦的教程文檔)
3.4 云壓測
3.4.1 云壓測介紹
顧名思義就是將壓測腳本部署在云端,通過云端對對我們的應用進行全方位壓測,只需要配置壓測的參數,無需準備實體機,云端自動給我們分配需要壓測的云主機,對被壓測目標進行壓測。
云壓測的優勢:
- 輕易的實現分布式部署
- 能夠模擬海量用戶的訪問
- 流量可以從全國各地發起,更加真實的反映用戶的體驗
- 全方位的監控壓測指標
- 文檔比較完善
當然了云壓測是一款商業產品,在使用的時候自然還是需要收費的,而且價格還是比較昂貴的~
3.4.2 阿里云 性能測試 PTS
PTS(Performance Testing Service)是面向所有技術背景人員的云化測試工具。有別于傳統工具的繁復,PTS以互聯網化的交互,提供性能測試、API調試和監測等多種能力。自研和適配開源的功能都可以輕松模擬任意體量的用戶訪問業務的場景,任務隨時發起,免去繁瑣的搭建和維護成本。更是緊密結合監控、流控等兄弟產品提供一站式高可用能力,高效檢驗和管理業務性能。
阿里云同樣還是支持滲透測試,通過模擬黑客對業務系統進行全面深入的安全測試。
3.4.3 騰訊云 壓測大師 LM
通過創建虛擬機器人模擬多用戶的并發場景,提供一整套完整的服務器壓測解決方案
4、go-stress-testing go語言實現的壓測工具
4.1 介紹
go-stress-testing 是go語言實現的簡單壓測工具,源碼開源、支持二次開發,可以壓測http、webSocket請求,使用協程模擬單個用戶,可以更高效的利用CPU資源。
4.2 用法
- 支持參數:
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文件進行壓測
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
4.3 實現
具體需求可以查看項目源碼
項目目錄結構
|____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 // 項目依賴目錄
4.4 go-stress-testing 對 Golang web 壓測
這里使用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
- go server
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 壓測命令
./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
5、壓測工具的比較
5.1 比較
- | ab | locust | Jmeter | go-stress-testing | 云壓測 |
---|---|---|---|---|---|
實現語言 | C | Python | Java | Golang | - |
UI界面 | 無 | 有 | 有 | 無 | 無 |
優勢 | 使用簡單,上手簡單 | 支持分布式、壓測數據支持導出 | 插件豐富,支持生成HTML報告 | 項目開源,使用簡單,沒有依賴,支持webSocket壓測 | 更加真實的模擬用戶,支持更高的壓測力度 |
5.2 如何選擇壓測工具
這個世界上沒有最好的,只有最適合的,工具千千萬,選擇一款適合你的才是最重要的
在實際使用中有各種場景,選擇工具的時候就需要考慮這些:
明確你的目的,需要做什么壓測、壓測的目標是什么?
使用的工具你是否熟悉,你愿意花多大的成本了解它?
你是為了測試還是想了解其中的原理?
工具是否能支持你需要壓測的場景
6、單臺機器100w連接壓測實戰
6.1 說明
之前寫了一篇文章,基于websocket單臺機器支持百萬連接分布式聊天(IM)系統(不了解這個項目可以查看上一篇或搜索一下文章),這里我們要實現單臺機器支持100W連接的壓測
目標:
- 單臺機器能保持100W個長連接
- 機器的CPU、內存、網絡、I/O 狀態都正常
說明:
gowebsocket 分布式聊天(IM)系統:
- 之前用戶連接以后有個全員廣播,這里需要將用戶連接、退出等事件關閉
- 服務器準備:
由于自己手上沒有自己的服務器,所以需要臨時購買的云服務器
壓測服務器:
16臺(稍后解釋為什么需要16臺機器)
CPU: 2核
內存: 8G
硬盤: 20G
系統: CentOS 7.6
被壓測服務:
1臺
CPU: 4核
內存: 32G
硬盤: 20G SSD
系統: CentOS 7.6
6.2 內核優化
- 修改程序最大打開文件數
被壓測服務器需要保持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
查看配置是否生效
6.3 客戶端配置
由于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~65000 -
tcp_mem
確定TCP棧應該如何反映內存使用,每個值的單位都是內存頁(通常是4KB)。第一個值是內存使用的下限;第二個值是內存壓力模式開始對緩沖區使用應用壓力的上限;第三個值是內存使用的上限。在這個層次上可以將報文丟棄,從而減少對內存的使用。對于較大的BDP可以增大這些值(注意,其單位是內存頁而不是字節) -
tcp_rmem
為自動調優定義socket使用的內存。第一個值是為socket接收緩沖區分配的最少字節數;第二個值是默認值(該值會被rmem_default覆蓋),緩沖區在系統負載不重的情況下可以增長到這個值;第三個值是接收緩沖區空間的最大字節數(該值會被rmem_max覆蓋)。 -
tcp_wmem
為自動調優定義socket使用的內存。第一個值是為socket發送緩沖區分配的最少字節數;第二個值是默認值(該值會被wmem_default覆蓋),緩沖區在系統負載不重的情況下可以增長到這個值;第三個值是發送緩沖區空間的最大字節數(該值會被wmem_max覆蓋)。
6.4 準備
在被壓測服務器上啟動Server服務(gowebsocket)
查看被壓測服務器的內網端口
登錄上16臺壓測服務器,這里我提前把需要優化的系統做成了鏡像,申請機器的時候就可以直接使用這個鏡像(參數已經調好)
- 啟動壓測
./go_stress_testing_linux -c 62500 -n 1 -u ws://192.168.0.74:443/acc
62500*16 = 100W
正好可以達到我們的要求
建立連接以后,-n 1
發送一個ping的消息給服務器,收到響應以后保持連接不中斷
通過 gowebsocket服務器的http接口,實時查詢連接數和項目啟動的協程數
壓測過程中查看系統狀態
# linux 命令
ps # 查看進程內存、cup使用情況
iostat # 查看系統IO情況
nload # 查看網絡流量情況
/proc/pid/status # 查看進程狀態
6.5 壓測數據
壓測以后,查看連接數到100W,然后保持10分鐘觀察系統是否正常
觀察以后,系統運行正常、CPU、內存、I/O 都正常,打開頁面都正常
壓測完成以后的數據
查看goWebSocket連接數統計,可以看到 clientsLen連接數為100W,goroutine數量2000008個,每個連接兩個goroutine加上項目啟動默認的8個。這里可以看到連接數滿足了100W
從壓測服務上查看連接數是否達到了要求,壓測完成的統計數據并發數為62500,是每個客戶端連接的數量,總連接數: 62500*16=100W
,
- 記錄內存使用情況,分別記錄了1W到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連接已經滿足~
7、總結
到這里壓測總算完成,本次壓測花費16元巨款。
單臺機器支持100W連接是實測是滿足的,但是實際業務比較復雜,還是需要持續優化~
本文通過介紹什么是壓測,在什么情況下需要壓測,通過單臺機器100W長連接的壓測實戰了解Linux內核的參數的調優。如果覺得現有的壓測工具不適用,可以自己實現或者是改造成屬于自己的自己的工具。
8、參考文獻
基于websocket單臺機器支持百萬連接分布式聊天(IM)系統
https://github.com/link1st/go-stress-testing
github 搜:link1st 查看項目 go-stress-testing