36 | 套路篇:怎么评估系统的网络性能?
生活随笔
收集整理的這篇文章主要介紹了
36 | 套路篇:怎么评估系统的网络性能?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
上一節,回顧了經典的 C10K 和 C1000K 問題。簡單回顧一下,C10K 是指如何單機同時處理 1 萬個請求(并發連接 1 萬)的問題,而 C1000K 則是單機支持處理 100 萬個請求(并發連接 100 萬)的問題。 I/O 模型的優化,是解決 C10K 問題的最佳良方。Linux 2.6 中引入的 epoll,完美解決了 C10K 的問題,并一直沿用至今。今天的很多高性能網絡方案,仍都基于 epoll。 自然,隨著互聯網技術的普及,催生出更高的性能需求。從 C10K 到 C100K,我們只需要增加系統的物理資源,就可以滿足要求;但從 C100K 到 C1000K ,光增加物理資源就不夠了。 這時,就要對系統的軟硬件進行統一優化,從硬件的中斷處理,到網絡協議棧的文件描述符數量、連接狀態跟蹤、緩存隊列,再到應用程序的工作模型等的整個網絡鏈路,都需要深入優化。 再進一步,要實現 C10M,就不是增加物理資源、調優內核和應用程序可以解決的問題了。這時內核中冗長的網絡協議棧就成了最大的負擔。
- 需要用 XDP 方式,在內核協議棧之前,先處理網絡包。
- 或基于 DPDK ,直接跳過網絡協議棧,在用戶空間通過輪詢的方式處理。
性能指標回顧
在評估網絡性能前,我們先來回顧一下,衡量網絡性能的指標。在 Linux 網絡基礎篇中,我們曾經說到,帶寬、吞吐量、延時、PPS 等,都是最常用的網絡性能指標。還記得它們的具體含義嗎?你可以先思考一下,再繼續下面的內容。- 首先,帶寬,表示鏈路的最大傳輸速率,單位是 b/s(比特 / 秒)。在你為服務器選購網卡時,帶寬就是最核心的參考指標。常用的帶寬有 1000M、10G、40G、100G 等。
- 第二,吞吐量,表示沒有丟包時的最大數據傳輸速率,單位通常為 b/s (比特 / 秒)或者 B/s(字節 / 秒)。吞吐量受帶寬的限制,吞吐量 / 帶寬也就是該網絡鏈路的使用率。
- 第三,延時,表示從網絡請求發出后,一直到收到遠端響應,所需要的時間延遲。這個指標在不同場景中可能會有不同的含義。它可以表示建立連接需要的時間(比如 TCP 握手延時),或者一個數據包往返所需時間(比如 RTT)。
- 最后,PPS,是 Packet Per Second(包 / 秒)的縮寫,表示以網絡包為單位的傳輸速率。PPS 通常用來評估網絡的轉發能力,而基于 Linux 服務器的轉發,很容易受到網絡包大小的影響(交換機通常不會受到太大影響,即交換機可以線性轉發)。
網絡基準測試
熟悉了網絡的性能指標后,接下來,我們再來看看,如何通過性能測試來確定這些指標的基準值。 你可以先思考一個問題。我們已經知道,Linux 網絡基于 TCP/IP 協議棧,而不同協議層的行為顯然不同。那么,測試之前,你應該弄清楚,你要評估的網絡性能,究竟屬于協議棧的哪一層?換句話說,你的應用程序基于協議棧的哪一層呢? 根據前面學過的 TCP/IP 協議棧的原理,這個問題應該不難回答。比如:- 基于 HTTP 或者 HTTPS 的 Web 應用程序,顯然屬于應用層,需要我們測試 HTTP/HTTPS 的性能;
- 而對大多數游戲服務器來說,為了支持更大的同時在線人數,通常會基于 TCP 或 UDP ,與客戶端進行交互,這時就需要我們測試 TCP/UDP 的性能;
- 當然,還有一些場景,是把 Linux 作為一個軟交換機或者路由器來用的。這種情況下,你更關注網絡包的處理能力(即 PPS),重點關注網絡層的轉發性能。
各協議層的性能測試
轉發性能
我們首先來看,網絡接口層和網絡層,它們主要負責網絡包的封裝、尋址、路由以及發送和接收。在這兩個網絡協議層中,每秒可處理的網絡包數 PPS,就是最重要的性能指標。特別是 64B 小包的處理能力,值得我們特別關注。那么,如何來測試網絡包的處理能力呢? 說到網絡包相關的測試,你可能會覺得陌生。不過,其實在專欄開頭的 CPU 性能篇中,我們就接觸過一個相關工具,也就是軟中斷案例中的 hping3。 在那個案例中,hping3 作為一個 SYN 攻擊的工具來使用。實際上, hping3 更多的用途,是作為一個測試網絡包處理能力的性能工具。 今天我再來介紹另一個更常用的工具,Linux 內核自帶的高性能網絡測試工具 pktgen。pktgen 支持豐富的自定義選項,方便你根據實際需要構造所需網絡包,從而更準確地測試出目標服務器的性能。 不過,在 Linux 系統中,你并不能直接找到 pktgen 命令。因為 pktgen 作為一個內核線程來運行,需要你加載 pktgen 內核模塊后,再通過 /proc 文件系統來交互。下面就是 pktgen 啟動的兩個內核線程和 /proc 文件系統的交互文件: $ modprobe pktgen $ ps -ef | grep pktgen | grep -v grep root 26384 2 0 06:17 ? 00:00:00 [kpktgend_0] root 26385 2 0 06:17 ? 00:00:00 [kpktgend_1] $ ls /proc/net/pktgen/ kpktgend_0 kpktgend_1 pgctrl pktgen 在每個 CPU 上啟動一個內核線程,并可以通過 /proc/net/pktgen 下面的同名文件,跟這些線程交互;而 pgctrl 則主要用來控制這次測試的開啟和停止。 如果 modprobe 命令執行失敗,說明你的內核沒有配置 CONFIG_NET_PKTGEN 選項。這就需要你配置 pktgen 內核模塊(即 CONFIG_NET_PKTGEN=m)后,重新編譯內核,才可以使用。 在使用 pktgen 測試網絡性能時,需要先給每個內核線程 kpktgend_X 以及測試網卡,配置 pktgen 選項,然后再通過 pgctrl 啟動測試。 以發包測試為例,假設發包機器使用的網卡是 eth0,而目標機器的 IP 地址為 192.168.0.30,MAC 地址為 11:11:11:11:11:11。 接下來,就是一個發包測試的示例。 # 定義一個工具函數,方便后面配置各種測試選項 function pgset() {local resultecho $1 > $PGDEVresult=`cat $PGDEV | fgrep "Result: OK:"`if [ "$result" = "" ]; thencat $PGDEV | fgrep Result:fi }# 為 0 號線程綁定 eth0 網卡 PGDEV=/proc/net/pktgen/kpktgend_0 pgset "rem_device_all" # 清空網卡綁定 pgset "add_device eth0" # 添加 eth0 網卡# 配置 eth0 網卡的測試選項 PGDEV=/proc/net/pktgen/eth0 pgset "count 1000000" # 總發包數量 pgset "delay 5000" # 不同包之間的發送延遲 (單位納秒) pgset "clone_skb 0" # SKB 包復制 pgset "pkt_size 64" # 網絡包大小 pgset "dst 192.168.0.30" # 目的 IP pgset "dst_mac 11:11:11:11:11:11" # 目的 MAC# 啟動測試 PGDEV=/proc/net/pktgen/pgctrl pgset "start" 稍等一會兒,測試完成后,結果可以從 /proc 文件系統中獲取。通過下面代碼段中的內容,我們可以查看剛才的測試報告: $ cat /proc/net/pktgen/eth0 Params: count 1000000 min_pkt_size: 64 max_pkt_size: 64frags: 0 delay: 0 clone_skb: 0 ifname: eth0flows: 0 flowlen: 0 ... Current:pkts-sofar: 1000000 errors: 0started: 1534853256071us stopped: 1534861576098us idle: 70673us ... Result: OK: 8320027(c8249354+d70673) usec, 1000000 (64byte,0frags)120191pps 61Mb/sec (61537792bps) errors: 0 你可以看到,測試報告主要分為三個部分:- 第一部分的 Params 是測試選項;
- 第二部分的 Current 是測試進度,其中, packts so far(pkts-sofar)表示已經發送了 100 萬個包,也就表明測試已完成。
- 第三部分的 Result 是測試結果,包含測試所用時間、網絡包數量和分片、PPS、吞吐量以及錯誤數。
TCP/UDP 性能
掌握了 PPS 的測試方法,接下來,我們再來看 TCP 和 UDP 的性能測試方法。說到 TCP 和 UDP 的測試,我想你已經很熟悉了,甚至可能一下子就能想到相應的測試工具,比如 iperf 或者 netperf。 特別是現在的云計算時代,在你剛拿到一批虛擬機時,首先要做的,應該就是用 iperf ,測試一下網絡性能是否符合預期。 iperf 和 netperf 都是最常用的網絡性能測試工具,測試 TCP 和 UDP 的吞吐量。它們都以客戶端和服務器通信的方式,測試一段時間內的平均吞吐量。 接下來,我們就以 iperf 為例,看一下 TCP 性能的測試方法。目前,iperf 的最新版本為 iperf3,你可以運行下面的命令來安裝: # Ubuntu apt-get install iperf3 # CentOS yum install iperf3 然后,在目標機器上啟動 iperf 服務端: # -s 表示啟動服務端,-i 表示匯報間隔,-p 表示監聽端口 $ iperf3 -s -i 1 -p 10000 接著,在另一臺機器上運行 iperf 客戶端,運行測試: # -c 表示啟動客戶端,192.168.0.30 為目標服務器的 IP # -b 表示目標帶寬 (單位是 bits/s) # -t 表示測試時間 # -P 表示并發數,-p 表示目標服務器監聽端口 $ iperf3 -c 192.168.0.30 -b 1G -t 15 -P 2 -p 10000 稍等一會兒(15 秒)測試結束后,回到目標服務器,查看 iperf 的報告: [ ID] Interval Transfer Bandwidth ... [SUM] 0.00-15.04 sec 0.00 Bytes 0.00 bits/sec sender [SUM] 0.00-15.04 sec 1.51 GBytes 860 Mbits/sec receiver 最后的 SUM 行就是測試的匯總結果,包括測試時間、數據傳輸量以及帶寬等。按照發送和接收,這一部分又分為了 sender 和 receiver 兩行。 從測試結果你可以看到,這臺機器 TCP 接收的帶寬(吞吐量)為 860 Mb/s, 跟目標的 1Gb/s 相比,還是有些差距的。HTTP 性能
從傳輸層再往上,到了應用層。有的應用程序,會直接基于 TCP 或 UDP 構建服務。當然,也有大量的應用,基于應用層的協議來構建服務,HTTP 就是最常用的一個應用層協議。比如,常用的 Apache、Nginx 等各種 Web 服務,都是基于 HTTP。 要測試 HTTP 的性能,也有大量的工具可以使用,比如 ab、webbench 等,都是常用的 HTTP 壓力測試工具。其中,ab 是 Apache 自帶的 HTTP 壓測工具,主要測試 HTTP 服務的每秒請求數、請求延遲、吞吐量以及請求延遲的分布情況等。 運行下面的命令,你就可以安裝 ab 工具: # Ubuntu $ apt-get install -y apache2-utils # CentOS $ yum install -y httpd-tools 接下來,在目標機器上,使用 Docker 啟動一個 Nginx 服務,然后用 ab 來測試它的性能。首先,在目標機器上運行下面的命令: $ docker run -p 80:80 -itd nginx 而在另一臺機器上,運行 ab 命令,測試 Nginx 的性能: # -c 表示并發請求數為 1000,-n 表示總的請求數為 10000 $ ab -c 1000 -n 10000 http://192.168.0.30/ ... Server Software: nginx/1.15.8 Server Hostname: 192.168.0.30 Server Port: 80...Requests per second: 1078.54 [#/sec] (mean) Time per request: 927.183 [ms] (mean) Time per request: 0.927 [ms] (mean, across all concurrent requests) Transfer rate: 890.00 [Kbytes/sec] receivedConnection Times (ms)min mean[+/-sd] median max Connect: 0 27 152.1 1 1038 Processing: 9 207 843.0 22 9242 Waiting: 8 207 843.0 22 9242 Total: 15 233 857.7 23 9268Percentage of the requests served within a certain time (ms)50% 2366% 2475% 2480% 2690% 27495% 119598% 233599% 4663100% 9268 (longest request) 可以看到,ab 的測試結果分為三個部分,分別是請求匯總、連接時間匯總還有請求延遲匯總。以上面的結果為例,我們具體來看。 在請求匯總部分,你可以看到:- Requests per second 為 1074;
- 每個請求的延遲(Time per request)分為兩行,第一行的 927 ms 表示平均延遲,包括了線程運行的調度時間和網絡請求響應時間,而下一行的 0.927ms ,則表示實際請求的響應時間;
- Transfer rate 表示吞吐量(BPS)為 890 KB/s。
應用負載性能
當你用 iperf 或者 ab 等測試工具,得到 TCP、HTTP 等的性能數據后,這些數據是否就能表示應用程序的實際性能呢?我想,你的答案應該是否定的。 比如,你的應用程序基于 HTTP 協議,為最終用戶提供一個 Web 服務。這時,使用 ab 工具,可以得到某個頁面的訪問性能,但這個結果跟用戶的實際請求,很可能不一致。因為用戶請求往往會附帶著各種各種的負載(payload),而這些負載會影響 Web 應用程序內部的處理邏輯,從而影響最終性能。 那么,為了得到應用程序的實際性能,就要求性能工具本身可以模擬用戶的請求負載,而 iperf、ab 這類工具就無能為力了。幸運的是,我們還可以用 wrk、TCPCopy、Jmeter 或者 LoadRunner 等實現這個目標。 以 wrk 為例,它是一個 HTTP 性能測試工具,內置了 LuaJIT,方便你根據實際需求,生成所需的請求負載,或者自定義響應的處理方法。 wrk 工具本身不提供 yum 或 apt 的安裝方法,需要通過源碼編譯來安裝。比如,你可以運行下面的命令,來編譯和安裝 wrk: $ https://github.com/wg/wrk $ cd wrk $ apt-get install build-essential -y $ make $ sudo cp wrk /usr/local/bin/ wrk 的命令行參數比較簡單。比如,我們可以用 wrk ,來重新測一下前面已經啟動的 Nginx 的性能。 # -c 表示并發連接數 1000,-t 表示線程數為 2 $ wrk -c 1000 -t 2 http://192.168.0.30/ Running 10s test @ http://192.168.0.30/2 threads and 1000 connectionsThread Stats Avg Stdev Max +/- StdevLatency 65.83ms 174.06ms 1.99s 95.85%Req/Sec 4.87k 628.73 6.78k 69.00%96954 requests in 10.06s, 78.59MB readSocket errors: connect 0, read 0, write 0, timeout 179 Requests/sec: 9641.31 Transfer/sec: 7.82MB 這里使用 2 個線程、并發 1000 連接,重新測試了 Nginx 的性能。你可以看到,每秒請求數為 9641,吞吐量為 7.82MB,平均延遲為 65ms,比前面 ab 的測試結果要好很多。 這也說明,性能工具本身的性能,對性能測試也是至關重要的。不合適的性能工具,并不能準確測出應用程序的最佳性能。 當然,wrk 最大的優勢,是其內置的 LuaJIT,可以用來實現復雜場景的性能測試。wrk 在調用 Lua 腳本時,可以將 HTTP 請求分為三個階段,即 setup、running、done,如下圖所示: (圖片來自網易云博客) 比如,你可以在 setup 階段,為請求設置認證參數(來自于 wrk 官方示例): -- example script that demonstrates response handling and -- retrieving an authentication token to set on all future -- requeststoken = nil path = "/authenticate"request = function()return wrk.format("GET", path) endresponse = function(status, headers, body)if not token and status == 200 thentoken = headers["X-Token"]path = "/resource"wrk.headers["X-Token"] = tokenend end 而在執行測試時,通過 -s 選項,執行腳本的路徑: $ wrk -c 1000 -t 2 -s auth.lua http://192.168.0.30/ wrk 需要你用 Lua 腳本,來構造請求負載。這對于大部分場景來說,可能已經足夠了 。不過,它的缺點也正是,所有東西都需要代碼來構造,并且工具本身不提供 GUI 環境。 像 Jmeter 或者 LoadRunner(商業產品),則針對復雜場景提供了腳本錄制、回放、GUI 等更豐富的功能,使用起來也更加方便。小結
今天,我帶你一起回顧了網絡的性能指標,并學習了網絡性能的評估方法。 性能評估是優化網絡性能的前提,只有在你發現網絡性能瓶頸時,才需要進行網絡性能優化。根據 TCP/IP 協議棧的原理,不同協議層關注的性能重點不完全一樣,也就對應不同的性能測試方法。比如,- 在應用層,你可以使用 wrk、Jmeter 等模擬用戶的負載,測試應用程序的每秒請求數、處理延遲、錯誤數等;
- 而在傳輸層,則可以使用 iperf 等工具,測試 TCP 的吞吐情況;
- 再向下,你還可以用 Linux 內核自帶的 pktgen ,測試服務器的 PPS。
總結
以上是生活随笔為你收集整理的36 | 套路篇:怎么评估系统的网络性能?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 35丨基础篇:C10K和C1000K回顾
- 下一篇: 37 | 案例篇:DNS 解析时快时慢,