go實現的壓測工具【單臺機器100w連線壓測實戰】

link1st發表於2019-08-29

本文介紹壓測是什麼,解釋壓測的專屬名詞,教大家如何壓測。介紹市面上的常見壓測工具(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" 進入壓測頁面

locust 首頁

壓測介面右上角有:被壓測的地址、當前狀態、RPS、失敗率、開始或重啟按鈕

效能測試引數

  • Type 請求的型別,例如GET/POST

  • Name 請求的路徑

  • Request 當前請求的數量

  • Fails 當前請求失敗的數量

  • Median 中間值,單位毫秒,請求響應時間的中間值

  • Average 平均值,單位毫秒,請求的平均響應時間

  • Min 請求的最小伺服器響應時間,單位毫秒

  • Max 請求的最大伺服器響應時間,單位毫秒

  • Average size 單個請求的大小,單位位元組

  • Current RPS 代表吞吐量(Requests Per Second的縮寫),指的是某個併發使用者數下單位時間內處理的請求數。等效於QPS,其實可以看作同一個統計方式,只是叫法不同而已。

locust 壓測頁面

3.3 Jmeter

  • 簡介

Apache JMeter是Apache組織開發的基於Java的壓力測試工具。用於對軟體做壓力測試,它最初被設計用於Web應用測試,但後來擴充套件到其他測試領域。 JMeter能夠對應用程式做功能/迴歸測試,通過建立帶有斷言的指令碼來驗證你的程式返回了你期望的結果。

  • 安裝

訪問 https://jmeter-plugins.org/install/Install/ 下載解壓以後即可使用

  • 用法

JMeter的功能過於強大,這裡暫時不介紹用法,可以查詢相關文件使用(參考文獻中有推薦的教程文件)

3.4 雲壓測

3.4.1 雲壓測介紹

顧名思義就是將壓測指令碼部署在雲端,通過雲端對對我們的應用進行全方位壓測,只需要配置壓測的引數,無需準備實體機,雲端自動給我們分配需要壓測的雲主機,對被壓測目標進行壓測。

雲壓測的優勢:

  1. 輕易的實現分散式部署
  2. 能夠模擬海量使用者的訪問
  3. 流量可以從全國各地發起,更加真實的反映使用者的體驗
  4. 全方位的監控壓測指標
  5. 文件比較完善

當然了雲壓測是一款商業產品,在使用的時候自然還是需要收費的,而且價格還是比較昂貴的~

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資源。

  • 專案地址 https://github.com/link1st/go-stress-testing

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 在終端執行命令 copy 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-stress-testing01

  • 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

webSocket壓測伺服器

被壓測服務:

1臺

CPU: 4核 記憶體: 32G 硬碟: 20G SSD 系統: CentOS 7.6

webSocket被壓測伺服器

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 準備

  1. 在被壓測伺服器上啟動Server服務(gowebsocket)

  2. 檢視被壓測伺服器的內網埠

  3. 登入上16臺壓測伺服器,這裡我提前把需要優化的系統做成了映象,申請機器的時候就可以直接使用這個映象(引數已經調好)

壓測伺服器16臺準備

  1. 啟動壓測
 ./go_stress_testing_linux -c 62500 -n 1  -u ws://192.168.0.74:443/acc

62500*16 = 100W正好可以達到我們的要求

建立連線以後,-n 1傳送一個ping的訊息給伺服器,收到響應以後保持連線不中斷

  1. 通過 gowebsocket伺服器的http介面,實時查詢連線數和專案啟動的協程數

  2. 壓測過程中檢視系統狀態
# linux 命令
ps      # 檢視程式記憶體、cup使用情況
iostat  # 檢視系統IO情況
nload   # 檢視網路流量情況
/proc/pid/status # 檢視程式狀態

6.5 壓測資料

  • 壓測以後,檢視連線數到100W,然後保持10分鐘觀察系統是否正常

  • 觀察以後,系統執行正常、CPU、記憶體、I/O 都正常,開啟頁面都正常

  • 壓測完成以後的資料

檢視goWebSocket連線數統計,可以看到 clientsLen連線數為100W,goroutine數量2000008個,每個連線兩個goroutine加上專案啟動預設的8個。這裡可以看到連線數滿足了100W

檢視goWebSocket連線數統計

從壓測服務上檢視連線數是否達到了要求,壓測完成的統計資料併發數為62500,是每個客戶端連線的數量,總連線數: 62500*16=100W

壓測服務16臺 壓測完成

  • 記錄記憶體使用情況,分別記錄了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、參考文獻

效能測試工具

效能測試常見名詞解釋

效能測試名詞解釋

PV、TPS、QPS是怎麼計算出來的?

超實用壓力測試工具-ab工具

Locust 介紹

Jmeter效能測試 入門

基於websocket單臺機器支援百萬連線分散式聊天(IM)系統

https://github.com/link1st/go-stress-testing

github 搜:link1st 檢視專案 go-stress-testing

相關文章