go實現的壓測工具【單臺機器100w連線壓測實戰】
本文介紹壓測是什麼,解釋壓測的專屬名詞,教大家如何壓測。介紹市面上的常見壓測工具 (ab、locust、Jmeter、go 實現的壓測工具、雲壓測),對比這些壓測工具,教大家如何選擇一款適合自己的壓測工具,本文還有兩個壓測實戰專案:
- 單臺機器對 HTTP 短連線 QPS 1W+ 的壓測實戰
- 單臺機器 100W 長連線的壓測實戰
目錄
- 1、專案說明
- 1.1 go-stress-testing
- 1.2 專案體驗本文介紹壓測是什麼,解釋壓測的專屬名詞,教大家如何壓測。介紹市面上的常見壓測工具 (ab、locust、Jmeter、go 實現的壓測工具、雲壓測),對比這些壓測工具,教大家如何選擇一款適合自己的壓測工具,本文還有兩個壓測實戰專案:<ul><li>單臺機器對 HTTP 短連線 QPS 1W+ 的壓測實戰</li><li>單臺機器 100W 長連線的壓測實戰</li></ul><p> <a href="https://github.com/link1st/go-stress-testing" target="_blank">原文地址</a> (更好的閱讀格式)<br></p><h2>目錄</h2><ul><li>1、專案說明<ul><li>1.1 go-stress-testing</li><li>1.2 專案體驗</li></ul></li><li>2、壓測<ul><li>2.1 壓測是什麼</li><li>2.2 為什麼要壓測</li><li>2.3 壓測名詞解釋<ul><li>2.3.1 壓測型別解釋</li><li>2.3.2 壓測名詞解釋</li><li>2.3.3 機器效能指標解釋</li><li>2.3.4 訪問指標解釋</li></ul></li><li>3.4 如何計算壓測指標</li></ul></li><li>3、常見的壓測工具<ul><li>3.1 ab</li><li>3.2 locust</li><li>3.3 Jmete</li><li>3.4 雲壓測<ul><li>3.4.1 雲壓測介紹</li><li>3.4.2 阿里雲 效能測試 PTS</li><li>3.4.3 騰訊雲 壓測大師 LM</li></ul></li></ul></li><li>4、go-stress-testing go 語言實現的壓測工具<ul><li>4.1 介紹</li><li>4.2 用法</li><li>4.3 實現</li><li>4.4 go-stress-testing 對 Golang web 壓測</li></ul></li><li>5、壓測工具的比較<ul><li>5.1 比較</li><li>5.2 如何選擇壓測工具</li></ul></li><li>6、單臺機器 100w 連線壓測實戰<ul><li>6.1 說明</li><li>6.2 核心優化</li><li>6.3 客戶端配置</li><li>6.4 準備</li><li>6.5 壓測資料</li></ul></li><li>7、總結</li><li>8、參考文獻</li></ul><h2>1、專案說明</h2><h3>1.1 go-stress-testing</h3><p>go 實現的壓測工具,每個使用者用一個協程的方式模擬,最大限度的利用 CPU 資源</p><h3>1.2 專案體驗</h3><ul><li>可以在 mac/linux/windows 不同平臺下執行的命令</li><li><a href="https://github.com/link1st/go-stress-testing/releases">go-stress-testing</a;> 壓測工具下載地址</li></ul><p>引數說明:</p><p><code>-c</code> 表示併發數</p><p><code>-n</code> 每個併發執行請求的次數,總請求的次數 = 併發數 * 每個併發執行請求的次數</p><p><code>-u</code> 需要壓測的地址</p><pre># 執行 以 mac 為示例 ./go-stress-testing-mac -c 1 -n 100 -u https://www.baidu.com/</pre><ul><li> 壓測結果展示</li></ul><p> 執行以後,終端每秒鐘都會輸出一次結果,壓測完成以後輸出執行的壓測結果</p><p> 壓測結果展示:</p><pre>─────┬───────┬───────┬───────┬────────┬────────┬────────┬────────┬────────; 耗時│ 併發數 │ 成功數│ 失敗數 │ 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 ****************************</pre><p>引數解釋:</p><p><strong>耗時</strong>: 程式執行耗時。程式每秒鐘輸出一次壓測結果</p><p><strong>併發數</strong>: 併發數,啟動的協程數</p><p><strong>成功數</strong>: 壓測中,請求成功的數量</p><p><strong>失敗數</strong>: 壓測中,請求失敗的數量</p><p><strong>qps</strong>: 當前壓測的 QPS(每秒鐘處理請求數量)</p><p><strong>最長耗時</strong>: 壓測中,單個請求最長的響應時長</p><p><strong>最短耗時</strong>: 壓測中,單個請求最短的響應時長</p><p><strong>平均耗時</strong>: 壓測中,單個請求平均的響應時長</p><p><strong>錯誤碼</strong>: 壓測中,介面返回的 code 碼:返回次數的集合</p><h2>2、壓測</h2><h3>2.1 壓測是什麼</h3><p>壓測,即壓力測試,是確立系統穩定性的一種測試方法,通常在系統正常運作範圍之外進行,以考察其功能極限和隱患。</p><p>主要檢測伺服器的承受能力,包括使用者承受能力(多少使用者同時玩基本不影響質量)、流量承受等。</p><h3>2.2 為什麼要壓測</h3><ul><li>壓測的目的就是通過壓測 (模擬真實使用者的行為),測算出機器的效能 (單臺機器的 QPS),從而推算出系統在承受指定使用者數 (100W) 時,需要多少機器能支撐得住</li><li>壓測是在上線前為了應對未來可能達到的使用者數量的一次預估 (提前演練),壓測以後通過優化程式的效能或準備充足的機器,來保證使用者的體驗。</li></ul><h3>2.3 壓測名詞解釋</h3><h4>2.3.1 壓測型別解釋</h4><div><table><thead><tr><th><div><p>壓測型別</p></div></th><th><div><p>解釋 </p></div></th></tr></thead><tbody><tr><td><div><p>壓力測試 (Stress Testing) </p></div></td><td><div><p>也稱之為強度測試,測試一個系統的最大抗壓能力,在強負載 (大資料、高併發) 的情況下,測試系統所能承受的最大壓力,預估系統的瓶頸 </p></div></td></tr><tr><td><div><p>併發測試 (Concurrency Testing) </p></div></td><td><div><p>通過模擬很多使用者同一時刻訪問系統或對系統某一個功能進行操作,來測試系統的效能,從中發現問題 (併發讀寫、執行緒控制、資源爭搶) </p></div></td></tr><tr><td><div><p>耐久性測試 (Configuration Testing)</p></div></td><td><div><p>通過對系統在大負荷的條件下長時間執行,測試系統、機器的長時間執行下的狀況,從中發現問題 (記憶體洩漏、資料庫連線池不釋放、資源不回收) </p></div></td></tr></tbody></table></div><h4>2.3.2 壓測名詞解釋</h4><div><table><thead><tr><th><div><p>壓測名詞</p></div></th><th><div><p>解釋 </p></div></th></tr></thead><tbody><tr><td><div><p>併發 (Concurrency) </p></div></td><td><div><p>指一個處理器同時處理多個任務的能力 (邏輯上處理的能力) </p></div></td></tr><tr><td><div><p>並行 (Parallel) </p></div></td><td><div><p>多個處理器或者是多核的處理器同時處理多個不同的任務 (物理上同時執行) </p></div></td></tr><tr><td><div><p>QPS(每秒鐘查詢數量 Query Per Second)</p></div></td><td><div><p>伺服器每秒鐘處理請求數量 (req/sec 請求數/秒 一段時間內總請求數/請求時間) </p></div></td></tr><tr><td><div><p>事務 (Transactions)</p></div></td><td><div><p>是使用者一次或者是幾次請求的集合 </p></div></td></tr><tr><td><div><p>TPS(每秒鐘處理事務數量 Transaction Per Second)</p></div></td><td><div><p>伺服器每秒鐘處理事務數量 (一個事務可能包括多個請求) </p></div></td></tr><tr><td><div><p>請求成功數 (Request Success Number)</p></div></td><td><div><p>在一次壓測中,請求成功的數量 </p></div></td></tr><tr><td><div><p>請求失敗數 (Request Failures Number)</p></div></td><td><div><p>在一次壓測中,請求失敗的數量 </p></div></td></tr><tr><td><div><p>錯誤率 (Error Rate)</p></div></td><td><div><p>在壓測中,請求成功的數量與請求失敗數量的比率 </p></div></td></tr><tr><td><div><p>最大響應時間 (Max Response Time)</p></div></td><td><div><p>在一次事務中,從發出請求或指令系統做出的反映 (響應) 的最大時間 </p></div></td></tr><tr><td><div><p>最少響應時間 (Mininum Response Time)</p></div></td><td><div><p>在一次事務中,從發出請求或指令系統做出的反映 (響應) 的最少時間 </p></div></td></tr><tr><td><div><p>平均響應時間 (Average Response Time)</p></div></td><td><div><p>在一次事務中,從發出請求或指令系統做出的反映 (響應) 的平均時間 </p></div></td></tr></tbody></table></div><h4>2.3.3 機器效能指標解釋</h4><div><table><thead><tr><th><div><p>機器效能</p></div></th><th><div><p>解釋 </p></div></th></tr></thead><tbody><tr><td><div><p>CUP 利用率 (CPU Usage) </p></div></td><td><div><p>CUP 利用率分使用者態、系統態和空閒態,CPU 利用率是指:CPU 執行非系統空閒程式的時間與 CPU 總執行時間的比率 </p></div></td></tr><tr><td><div><p>記憶體使用率 (Memory usage) </p></div></td><td><div><p>記憶體使用率指的是此程式所開銷的記憶體。 </p></div></td></tr><tr><td><div><p>IO(Disk input/ output) </p></div></td><td><div><p>磁碟的讀寫包速率 </p></div></td></tr><tr><td><div><p>網路卡負載 (Network Load) </p></div></td><td><div><p>網路卡的進出頻寬,包量 </p></div></td></tr></tbody></table></div><h4>2.3.4 訪問指標解釋</h4><div><table><thead><tr><th><div><p>訪問</p></div></th><th><div><p>解釋 </p></div></th></tr></thead><tbody><tr><td><div><p>PV(頁面瀏覽量 Page View) </p></div></td><td><div><p>使用者每開啟 1 個網站頁面,記錄 1 個 PV。使用者多次開啟同一頁面,PV 值累計多次 </p></div></td></tr><tr><td><div><p>UV(網站獨立訪客 Unique Visitor) </p></div></td><td><div><p>通過網際網路訪問、流量網站的自然人。1 天內相同訪客多次訪問網站,只計算為 1 個獨立訪客 </p></div></td></tr></tbody></table></div><h3>2.4 如何計算壓測指標</h3><ul><li>壓測我們需要有目的性的壓測,這次壓測我們需要達到什麼目標 (如:單臺機器的效能為 100QPS?網站能同時滿足 100W 人同時線上)</li><li>可以通過以下計算方法來進行計算:</li><li>壓測原則:每天 80% 的訪問量集中在 20% 的時間裡,這 20% 的時間就叫做峰值</li><li>公式: ( 總 PV 數<em>80% ) / ( 每天的秒數</em>20% ) = 峰值時間每秒鐘請求數 (QPS)</li><li>機器: 峰值時間每秒鐘請求數 (QPS) / 單臺機器的 QPS = 需要的機器的數量</li><li>假設:網站每天的使用者數 (100W),每天的使用者的訪問量約為 3000W PV,這臺機器的需要多少 QPS?( 30000000*0.8 ) / (86400 * 0.2) ≈ 1389 (QPS)</li><li>假設:單臺機器的的 QPS 是 69,需要需要多少臺機器來支撐?1389 / 69 ≈ 20</li></ul><h2>3、常見的壓測工具</h2><h3>3.1 ab</h3><ul><li>簡介</li></ul><p>ApacheBench 是 Apache 伺服器自帶的一個 web 壓力測試工具,簡稱 ab。ab 又是一個命令列工具,對發起負載的本機要求很低,根據 ab 命令可以建立很多的併發訪問執行緒,模擬多個訪問者同時對某一 URL 地址進行訪問,因此可以用來測試目標伺服器的負載壓力。總的來說 ab 工具小巧簡單,上手學習較快,可以提供需要的基本效能指標,但是沒有圖形化結果,不能監控。</p><p>ab 屬於一個輕量級的壓測工具,結果不會特別準確,可以用作參考。</p><ul><li>安裝</li></ul><pre># 在 linux 環境安裝 sudo yum -y install httpd</pre><ul><li>用法</li></ul><pre>Usage: ab [options] [http[s]://] hostname[:port]/path 用法:ab [選項] 地址
選項: Options are: -n requests # 執行的請求數,即一共發起多少請求。 -c concurrency # 請求併發數。 -s timeout # 指定每個請求的超時時間,預設是 30 秒。 -k # 啟用 HTTP KeepAlive 功能,即在一個 HTTP 會話中執行多個請求。預設時,不啟用 KeepAlive 功能。</pre><ul><li>壓測命令</li></ul><pre># 使用 ab 壓測工具,對百度的連結 請求 100 次,併發數 1 ab -n 100 -c 1 https://www.baidu.com/</pre><p> 壓測結果</p><pre>~; >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 Time per request: 94.301 ms Time per request: 94.301 ms 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)</pre><ul><li>主要關注的測試指標</li><li><code>Concurrency Level</code> 併發請求數</li><li><code>Time taken for tests</code> 整個測試時間</li><li><code>Complete requests</code> 完成請求個數</li><li><code>Failed requests</code> 失敗個數</li><li><code>Requests per second</code> 吞吐量,指的是某個併發使用者下單位時間內處理的請求數。等效於 QPS,其實可以看作同一個統計方式,只是叫法不同而已。</li><li><code>Time per request</code> 使用者平均請求等待時間</li><li><code>Time per request</code> 伺服器處理時間</li></ul><h3>3.2 Locust</h3><ul><li>簡介</li></ul><p>是非常簡單易用、分散式、python 開發的壓力測試工具。有圖形化介面,支援將壓測資料匯出。</p><ul><li>安裝</li></ul><pre># pip3 安裝 locust pip3 install locust
檢視是否安裝成功
locust -h
執行 Locust 分佈在多個程式/機器庫
pip3 install pyzmq
webSocket 壓測庫
pip3 install websocket-client</pre><ul><li>用法</li></ul><p>編寫壓測指令碼 <strong>test.py</strong></p><pre>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 # 執行事務之間使用者等待時間的上界(單位:毫秒)</pre><ul><li>啟動壓測</li></ul><pre>locust -f test.py --host=https://www.baidu.com</pre><p> 訪問; http://localhost:8089 進入壓測首頁</p><p>Number of users to simulate 模擬使用者數</p><p>Hatch rate (users spawned/second) 每秒鐘增加使用者數</p><p>點選 "Start swarming" 進入壓測頁面</p><figure><img src="https://ask.qcloudimg.com/http-save/5223005/vcb5xqqg7a.jpeg?imageView2/2/w/1620">&lt/figure&gtlocust; 首頁<p>壓測介面右上角有:被壓測的地址、當前狀態、RPS、失敗率、開始或重啟按鈕</p><p>效能測試引數</p><ul><li><code>Type</code> 請求的型別,例如 GET/POST</li><li><code>Name</code> 請求的路徑</li><li><code>Request</code> 當前請求的數量</li><li><code>Fails</code> 當前請求失敗的數量</li><li><code>Median</code> 中間值,單位毫秒,請求響應時間的中間值</li><li><code>Average</code> 平均值,單位毫秒,請求的平均響應時間</li><li><code>Min</code> 請求的最小伺服器響應時間,單位毫秒</li><li><code>Max</code> 請求的最大伺服器響應時間,單位毫秒</li><li><code>Average size</code> 單個請求的大小,單位位元組</li><li><code>Current RPS</code> 代表吞吐量 (Requests Per Second 的縮寫),指的是某個併發使用者數下單位時間內處理的請求數。等效於 QPS,其實可以看作同一個統計方式,只是叫法不同而已。</li></ul><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/3ylyetx8dt.jpeg?imageView2/2/w/1620">&ltfigcaption&gtlocust; 壓測頁面</figcaption></div></figure><h3>3.3 JMete</h3><ul><li>簡介</li></ul><p>Apache JMeter 是 Apache 組織開發的基於 Java 的壓力測試工具。用於對軟體做壓力測試,它最初被設計用於 Web 應用測試,但後來擴充套件到其他測試領域。</p><p>JMeter 能夠對應用程式做功能/迴歸測試,通過建立帶有斷言的指令碼來驗證你的程式返回了你期望的結果。</p><ul><li>安裝</li></ul><p>訪問 <a href="https://jmeter-plugins.org/install/Install/">https://jmeter-plugins.org/install/Install/</a;> 下載解壓以後即可使用</p><ul><li>用法</li></ul><p>JMeter 的功能過於強大,這裡暫時不介紹用法,可以查詢相關文件使用 (參考文獻中有推薦的教程文件)</p><h3>3.4 雲壓測</h3><h4>3.4.1 雲壓測介紹</h4><p>顧名思義就是將壓測指令碼部署在雲端,通過雲端對對我們的應用進行全方位壓測,只需要配置壓測的引數,無需準備實體機,雲端自動給我們分配需要壓測的雲主機,對被壓測目標進行壓測。</p><p>雲壓測的優勢:</p><ol><li>輕易的實現分散式部署</li><li>能夠模擬海量使用者的訪問</li><li>流量可以從全國各地發起,更加真實的反映使用者的體驗</li><li>全方位的監控壓測指標</li><li>文件比較完善</li></ol><p>當然了雲壓測是一款商業產品,在使用的時候自然還是需要收費的,而且價格還是比較昂貴的~</p><h4>3.4.2 阿里雲 效能測試 PTS</h4><p>PTS(Performance Testing Service)是面向所有技術背景人員的雲化測試工具。有別於傳統工具的繁複,PTS 以網際網路化的互動,提供效能測試、API 除錯和監測等多種能力。自研和適配開源的功能都可以輕鬆模擬任意體量的使用者訪問業務的場景,任務隨時發起,免去繁瑣的搭建和維護成本。更是緊密結合監控、流控等兄弟產品提供一站式高可用能力,高效檢驗和管理業務效能。</p><p>阿里雲同樣還是支援滲透測試,通過模擬黑客對業務系統進行全面深入的安全測試。</p><h4>3.4.3 騰訊雲 壓測大師 LM</h4><p>通過建立虛擬機器器人模擬多使用者的併發場景,提供一整套完整的伺服器壓測解決方案</p><h2>4、go-stress-testing go 語言實現的壓測工具</h2><h3>4.1 介紹</h3><ul><li>go-stress-testing 是 go 語言實現的簡單壓測工具,原始碼開源、支援二次開發,可以壓測 http、webSocket 請求,使用協程模擬單個使用者,可以更高效的利用 CPU 資源。</li><li>專案地址 <a href="https://github.com/link1st/go-stress-testing">https://github.com/link1st/go-stress-testing</a></li></ul><h3>4.2; 用法</h3><ul><li><a href="https://github.com/link1st/go-stress-testing/releases">go-stress-testing</a;> 下載地址</li><li>支援引數:</li></ul><pre>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")</pre><ul><li><code>-n</code> 是單個使用者請求的次數,請求總次數 = <code>-c</code>* <code>-n</code>, 這裡考慮的是模擬使用者行為,所以這個是每個使用者請求的次數</li><li>下載以後執行下面命令即可壓測</li><li>使用示例:</li></ul><pre># 檢視用法 ./go-stress-testing-mac
使用請求百度頁面
./go-stress-testing-mac -c 1 -n 100 -u https://www.baidu.com/
使用 debug 模式請求百度頁面
./go-stress-testing-mac -c 1 -n 1 -d true -u https://www.baidu.com/
使用 curl 檔案 (檔案在 curl 目錄下) 的方式請求
./go-stress-testing-mac -c 1 -n 1 -p curl/baidu.curl.txt
壓測 webSocket 連線
./go-stress-testing-mac -c 10 -n 10 -u ws://127.0.0.1:8089/acc</pre><ul><li>使用 curl 檔案進行壓測</li></ul><p>curl 是 Linux 在命令列下的工作的檔案傳輸工具,是一款很強大的 http 命令列工具。</p><p>使用 curl 檔案可以壓測使用非 GET 的請求,支援設定 http 請求的 method、cookies、header、body 等引數</p><p>chrome 瀏覽器生成 curl 檔案,開啟開發者模式 (快捷鍵 F12),如圖所示,生成 curl 在終端執行命令</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/gdvg0m5mn.jpeg?imageView2/2/w/1620">&ltfigcaption&gtcopy; cURL</figcaption></div></figure><p>生成內容貼上到專案目錄下的<strong>curl/baidu.curl.txt</strong>檔案中,執行下面命令就可以從 curl.txt 檔案中讀取需要壓測的內容進行壓測了</p><pre># 使用 curl 檔案 (檔案在 curl 目錄下) 的方式請求 go run main.go -c 1 -n 1 -p curl/baidu.curl.txt</pre><h3>4.3 實現</h3><ul><li>具體需求可以檢視專案原始碼</li><li>專案目錄結構</li></ul><pre>|_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 // 專案依賴目錄</pre><h3>4.4 go-stress-testing 對 Golang web 壓測</h3><p>這裡使用 go-stress-testing 對 go server 進行壓測 (部署在同一臺機器上),並統計壓測結果</p><ul><li>申請的伺服器配置</li></ul><p>CPU: 4 核 (Intel Xeon(Cascade Lake) Platinum 8269 2.5 GHz/3.2 GHz)</p><p>記憶體: 16G</p><p>硬碟: 20G SSD</p><p>系統: CentOS 7.6</p><p>go version: go1.12.9 linux/amd64</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/r5zg8uwary.jpeg?imageView2/2/w/1620">&ltfigcaption&gtgo-stress-testing01&lt/figcaption&gt</div>&lt/figure&gt<ul><li>go; serve</li></ul><pre>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) } }</pre><ul><li>go_stress_testing 壓測命令</li></ul><pre>./go_stress_testing_linux -c 100 -n 10000 -u http://127.0.0.1:8088/</pre><ul><li> 壓測結果</li></ul><div><table><thead><tr><th><div><p> 併發數; </p></div></th><th><div><p>go_stress_testing QPS </p></div></th></tr></thead><tbody><tr><td><div><p>1 </p></div></td><td><div><p>6394.86 </p></div></td></tr><tr><td><div><p>4 </p></div></td><td><div><p>16909.36</p></div></td></tr><tr><td><div><p>10 </p></div></td><td><div><p>18456.81</p></div></td></tr><tr><td><div><p>20 </p></div></td><td><div><p>19490.50</p></div></td></tr><tr><td><div><p>30 </p></div></td><td><div><p>19947.47</p></div></td></tr><tr><td><div><p>50 </p></div></td><td><div><p>19922.56</p></div></td></tr><tr><td><div><p>80 </p></div></td><td><div><p>19155.33</p></div></td></tr><tr><td><div><p>100 </p></div></td><td><div><p>18336.46</p></div></td></tr><tr><td><div><p>200 </p></div></td><td><div><p>16813.86</p></div></td></tr></tbody></table></div><p>從壓測的結果上看:效果還不錯,壓測 QPS 有接近 2W</p><h2>5、壓測工具的比較</h2><h3>5.1 比較</h3><div><table><thead><tr><th><div><ul><li> </li></ul></div></th><th><div><p>ab </p></div></th><th><div><p>locust </p></div></th><th><div><p>Jmeter </p></div></th><th><div><p>go-stress-testing </p></div></th><th><div><p>雲壓測 </p></div></th></tr></thead><tbody><tr><td><div><p>實現語言</p></div></td><td><div><p>C </p></div></td><td><div><p>Python</p></div></td><td><div><p>Java </p></div></td><td><div><p>Golang </p></div></td><td><div><ul><li></li></ul></div></td></tr><tr><td><div><p>UI 介面 </p></div></td><td><div><p>無 </p></div></td><td><div><p>有 </p></div></td><td><div><p>有 </p></div></td><td><div><p>無 </p></div></td><td><div><p>無 </p></div></td></tr><tr><td><div><p>優勢 </p></div></td><td><div><p>使用簡單,上手簡單 </p></div></td><td><div><p>支援分散式、壓測資料支援匯出 </p></div></td><td><div><p>外掛豐富,支援生成 HTML 報告 </p></div></td><td><div><p>專案開源,使用簡單,沒有依賴,支援 webSocket 壓測 </p></div></td><td><div><p>更加真實的模擬使用者,支援更高的壓測力度 </p></div></td></tr></tbody></table></div><h3>5.2 如何選擇壓測工具</h3><p>這個世界上<strong>沒有最好的,只有最適合的</strong>,工具千千萬,選擇一款適合你的才是最重要的</p><p>在實際使用中有各種場景,選擇工具的時候就需要考慮這些:</p><ul><li>明確你的目的,需要做什麼壓測、壓測的目標是什麼?</li><li>使用的工具你是否熟悉,你願意花多大的成本瞭解它?</li><li>你是為了測試還是想了解其中的原理?</li><li>工具是否能支援你需要壓測的場景</li></ul><h2>6、單臺機器 100w 連線壓測實戰</h2><h3>6.1 說明</h3><p>之前寫了一篇文章,<a href="https://github.com/link1st/gowebsocket"> 基於 websocket 單臺機器支援百萬連線分散式聊天 (IM) 系統</a>(不瞭解這個專案可以檢視上一篇或搜尋一下文章),這裡我們要實現單臺機器支援 100W 連線的壓測</p><p> 目標:</p><ul><li> 單臺機器能保持 100W 個長連線</li><li> 機器的 CPU、記憶體、網路、I/O; 狀態都正常</li></ul><p>說明:</p><p>gowebsocket 分散式聊天 (IM) 系統:</p><ul><li>之前使用者連線以後有個全員廣播,這裡需要將使用者連線、退出等事件關閉</li><li>伺服器準備:由於自己手上沒有自己的伺服器,所以需要臨時購買的<a href="https://cloud.tencent.com/product/cvm?from=10680"> 雲伺服器</a></li></ul><p> 壓測伺服器:</p><p>16 臺 (稍後解釋為什麼需要 16 臺機器)</p><p>CPU:; 2 核</p><p>記憶體: 8G</p><p>硬碟: 20G</p><p>系統: CentOS 7.6</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/8wyg6bknkl.jpeg?imageView2/2/w/1620">&ltfigcaption&gtwebSocket 壓測伺服器&lt/figcaption&gt</div>&lt/figure&gt<p> 被壓測服務:</p><p>1 臺</p><p>CPU:; 4 核</p><p>記憶體: 32G</p><p>硬碟: 20G SSD</p><p>系統: CentOS 7.6</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/e0dl2wzxq3.jpeg?imageView2/2/w/1620">&ltfigcaption&gtwebSocket 被壓測伺服器&lt/figcaption&gt</div>&lt/figure&gt<h3>6.2; 核心優化</h3><ul><li>修改程式最大開啟檔案數</li></ul><p>被壓測伺服器需要保持 100W 長連線,客戶和伺服器端是通過 socket 通訊的,每個連線需要建立一個 socket,程式需要保持 100W 長連線就需要單個程式能開啟 100W 個檔案控制程式碼</p><pre># 檢視系統預設的值 ulimit -n
設定最大開啟檔案數
ulimit -n 1040000</pre><p>這裡設定的要超過 100W,程式除了有 100W 連線還有其它資源連線 (資料庫、資源等連線),這裡設定為 104W</p><p>centOS 7.6 上述設定不生效,需要手動修改配置檔案</p><p><code>vim /etc/security/limits.conf</code></p><p>這裡需要把硬限制和軟限制、root 使用者和所有使用者都設定為 1040000</p><p>core 是限制核心檔案的大小,這裡設定為 unlimited</p><pre># 新增以下引數 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</pre><p>注意:</p><p><code>/proc/sys/fs/file-max</code> 表示系統級別的能夠開啟的檔案控制程式碼的數量,不能小於 limits 中設定的值</p><p>如果 file-max 的值小於 limits 設定的值會導致系統重啟以後無法登入</p><pre># file-max 設定的值參考 cat /proc/sys/fs/file-max 12553500</pre><p>修改以後重啟伺服器,<code>ulimit -n</code> 檢視配置是否生效</p><h3>6.3 客戶端配置</h3><p>由於 linux 埠的範圍是 <code>0~65535(2^16-1)</code>這個和作業系統無關,不管 linux 是 32 位的還是 64 位的</p><p>這個數字是由於 tcp 協議決定的,tcp 協議頭部表示埠只有 16 位,所以最大值只有 65535(如果每臺機器多幾個虛擬 ip 就能突破這個限制)</p><p>1024 以下是系統保留埠,所以能使用的 1024 到 65535</p><p>如果需要 100W 長連線,每臺機器有 65535-1024 個埠, 100W / (65535-1024) ≈ 15.5,所以這裡需要 16 臺伺服器</p><ul><li><code>vim /etc/sysctl.conf</code> 在檔案末尾新增</li></ul><pre>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</pre><p><code>sysctl -p</code> 修改配置以後使得配置生效命令</p><p>配置解釋:</p><ul><li><code>ip_local_port_range</code> 表示 TCP/UDP 協議允許使用的本地埠號 範圍:1024~65000</li><li><code>tcp_mem</code> 確定 TCP 棧應該如何反映記憶體使用,每個值的單位都是記憶體頁(通常是 4KB)。第一個值是記憶體使用的下限;第二個值是記憶體壓力模式開始對緩衝區使用應用壓力的上限;第三個值是記憶體使用的上限。在這個層次上可以將報文丟棄,從而減少對記憶體的使用。對於較大的 BDP 可以增大這些值(注意,其單位是記憶體頁而不是位元組)</li><li><code>tcp_rmem</code> 為自動調優定義 socket 使用的記憶體。第一個值是為 socket 接收緩衝區分配的最少位元組數;第二個值是預設值(該值會被 rmem_default 覆蓋),緩衝區在系統負載不重的情況下可以增長到這個值;第三個值是接收緩衝區空間的最大位元組數(該值會被 rmem_max 覆蓋)。</li><li><code>tcp_wmem</code> 為自動調優定義 socket 使用的記憶體。第一個值是為 socket 傳送緩衝區分配的最少位元組數;第二個值是預設值(該值會被 wmem_default 覆蓋),緩衝區在系統負載不重的情況下可以增長到這個值;第三個值是傳送緩衝區空間的最大位元組數(該值會被 wmem_max 覆蓋)。</li></ul><h3>6.4 準備</h3><ol><li>在被壓測伺服器上啟動 Server 服務 (gowebsocket)</li><li>檢視被壓測伺服器的內網埠</li><li>登入上 16 臺壓測伺服器,這裡我提前把需要優化的系統做成了映象,申請機器的時候就可以直接使用這個映象 (引數已經調好)</li></ol><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/glwexcc6a3.jpeg?imageView2/2/w/1620">&ltfigcaption&gt 壓測伺服器 16 臺準備&lt/figcaption&gt</div>&lt/figure&gt<ol><li> 啟動壓測</li></ol><pre;> ./go_stress_testing_linux -c 62500 -n 1 -u ws://192.168.0.74:443/acc</pre><p><code>62500*16 = 100W</code>正好可以達到我們的要求</p><p>建立連線以後,<code>-n 1</code>傳送一個<strong>ping</strong>的訊息給伺服器,收到響應以後保持連線不中斷</p><ol><li>通過 gowebsocket 伺服器的 http 介面,實時查詢連線數和專案啟動的協程數</li><li>壓測過程中檢視系統狀態</li></ol><pre># linux 命令 ps # 檢視程式記憶體、cup 使用情況 iostat # 檢視系統 IO 情況 nload # 檢視網路流量情況 /proc/pid/status # 檢視程式狀態</pre><h3>6.5 壓測資料</h3><ul><li>壓測以後,檢視連線數到 100W,然後保持 10 分鐘觀察系統是否正常</li><li>觀察以後,系統執行正常、CPU、記憶體、I/O 都正常,開啟頁面都正常</li><li>壓測完成以後的資料</li></ul><p>檢視 goWebSocket 連線數統計,可以看到 <strong>clientsLen</strong>連線數為 100W,<strong>goroutine</strong>數量 2000008 個,每個連線兩個 goroutine 加上專案啟動預設的 8 個。這裡可以看到連線數滿足了 100W</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/f02vrgcht0.jpeg?imageView2/2/w/1620">&ltfigcaption&gt 檢視 goWebSocket 連線數統計&lt/figcaption&gt</div>&lt/figure&gt<p> 從壓測服務上檢視連線數是否達到了要求,壓測完成的統計資料併發數為 62500,是每個客戶端連線的數量,總連線數:; <code>62500*16=100W</code>,</p><figure><div><img src="https://ask.qcloudimg.com/http-save/5223005/f4hkh4u0u1.jpeg?imageView2/2/w/1620">&ltfigcaption&gt 壓測服務 16 臺; 壓測完成</figcaption></div></figure><ul><li>記錄記憶體使用情況,分別記錄了 1W 到 100W 連線數記憶體使用情況</li></ul><div><table><thead><tr><th><div><p>連線數 </p></div></th><th><div><p>記憶體</p></div></th></tr></thead><tbody><tr><td><div><p>10000 </p></div></td><td><div><p>281M </p></div></td></tr><tr><td><div><p>100000 </p></div></td><td><div><p>2.7g </p></div></td></tr><tr><td><div><p>200000 </p></div></td><td><div><p>5.4g </p></div></td></tr><tr><td><div><p>500000 </p></div></td><td><div><p>13.1g</p></div></td></tr><tr><td><div><p>1000000 </p></div></td><td><div><p>25.8g</p></div></td></tr></tbody></table></div><p>100W 連線時的檢視記憶體詳細資料:</p><pre>cat /proc/pid/status VmSize: 27133804 kB</pre><p><code>27133804/1000000≈27.1</code> 100W 連線,佔用了 25.8g 的記憶體,粗略計算了一下,一個連線佔用了 27.1Kb 的記憶體,由於 goWebSocket 專案每個使用者連線起了兩個協程處理使用者的讀寫事件,所以記憶體佔用稍微多一點</p><p>如果需要如何減少記憶體使用可以參考 <strong>@Roy11568780</strong> 大佬給的解決方案</p><blockquote><p>傳統的 golang 中是採用的一個 goroutine 迴圈 read 的方法對應每一個 socket。實際百萬鏈路場景中這是巨大的資源浪費,優化的原理也不是什麼新東西,golang 中一樣也可以使用 epoll 的,把 fd 拿到 epoll 中,檢測到事件然後在協程池裡面去讀就行了,看情況讀寫分別 10-20 的協程 goroutine 池應該就足夠了</p></blockquote><p>至此,壓測已經全部完成,單臺機器支援 100W 連線已經滿足~</p><h2>7、總結</h2><p>到這裡壓測總算完成,本次壓測花費 16 元鉅款。</p><p>單臺機器支援 100W 連線是實測是滿足的,但是實際業務比較複雜,還是需要持續優化~</p><p>本文通過介紹什麼是壓測,在什麼情況下需要壓測,通過單臺機器 100W 長連線的壓測實戰了解 Linux 核心的引數的調優。如果覺得現有的壓測工具不適用,可以自己實現或者是改造成屬於自己的自己的工具。</p><h2>8、參考文獻</h2><p>效能測試工具</p><p>效能測試常見名詞解釋</p><p>效能測試名詞解釋</p><p>PV、TPS、QPS 是怎麼計算出來的?</p><p>超實用壓力測試工具-ab 工具</p><p>Locust 介紹</p><p>Jmeter 效能測試 入門</p><p>基於 websocket 單臺機器支援百萬連線分散式聊天 (IM) 系統</p><p>https://github.com/link1st/go-stress-testing</p><p>github; 搜:link1st 檢視專案 go-stress-testing</p><p><br></p>
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 基於 JMeter的壓測工具的實現JMeter
- 5. 堪比JMeter的.Net壓測工具 - Crank 實戰篇 - 介面以及場景壓測JMeter
- 一次壓測實戰的覆盤
- 有贊全鏈路壓測實戰
- 超實用壓力測試工具-ab工具
- sysbench壓測實踐
- 壓測工具 wrk
- kafka壓測工具Kafka
- 介面高併發壓測入門實戰
- 壓測工具之Sysbench(1_系統壓測)
- 如何做程式碼單元壓力測試?【JWordPress前臺專案實戰】
- apache ab壓力測試工具-批次壓測指令碼Apache指令碼
- 壓測工具之Sysbench1.0(2_MySQL壓測)MySql
- Jmeter-壓測工具JMeter
- 壓力測試工具
- 效能壓測工具 —— wrk
- 壓測工具jemiter使用MIT
- 實現Python壓力測試工具|Python 主題月Python
- jmeter壓力測試實現負載均衡JMeter負載
- ClickHouse與Elasticsearch壓測實踐Elasticsearch
- Go 效能壓測工具之wrk介紹與使用Go
- 【工具】MySQL 壓測工具之mydbtestMySql
- 壓縮工具效能測試
- [心得]Tsung壓測工具科普
- Webbench網站壓測工具Web網站
- 告別傳統壓測:全鏈路壓測在中通的實踐分享
- 很好用的壓測工具 - Apache Bench工具Apache
- 效能測試:主流壓測工具介紹
- canvas實現的前端壓縮裁剪工具Canvas前端
- 介面壓測實踐-壓力測試常見引數解釋說明
- 全鏈路壓測(5):生產全鏈路壓測實施全流程
- 全鏈路壓測平臺(Quake)在美團中的實踐
- locust多程序實現分散式壓測遇到的問題分散式
- 實用的壓縮解壓工具:WinZip for MacMac
- 高德全鏈路壓測——精準控壓的建設實踐
- 實用測試技能分享:APP壓力穩定性測試之Monkey入門實戰APP
- NoSQLBench壓測工具入門教程SQL
- 壓力測試工具之FIO