Linux 網路效能指標

jiayou111發表於2024-09-11

目錄
  • 網路效能指標
  • 檢視網路配置
  • 檢視socket資訊
  • 檢視網路吞吐率和PPS
  • 檢視連通性和延時

Linux 網路協議棧是根據 TCP/IP 模型來實現的,TCP/IP 模型由應用層、傳輸層、網路層和網路介面層,共四層組成,每一層都有各自的職責。

應用程式要傳送資料包時,通常是透過 socket 介面,於是就會發生系統呼叫,把應用層的資料複製到核心裡的 socket 層,接著由網路協議棧從上到下逐層處理後,最後才會送到網路卡傳送出去。

而對於接收網路包時,同樣也要經過網路協議逐層處理,不過處理的方向與傳送資料時是相反的,也就是從下到上的逐層處理,最後才送到應用程式。

網路的速度往往跟使用者體驗是掛鉤的,那我們又該用什麼指標來衡量 Linux 的網路效能呢?以及如何分析網路問題呢?

網路效能指標

通常是以4個指標來衡量網路的效能,分別是頻寬、延時、吞吐率、PPS(Packet Per Second),它們表示的意義如下:

  • 頻寬,表示鏈路的最大傳輸速率,單位是 b/s(位元/秒),頻寬越大,其傳輸能力就越強。
  • 延時,表示請求資料包傳送後,收到對端響應,所需要的時間延遲。不同的場景有著不同的含義,比如可以表示建立 TCP 連線所需的時間延遲,或一個資料包往返所需的時間延遲。
  • 吞吐率,表示單位時間內成功傳輸的資料量,單位是 b/s(位元/秒)或者 B/s(位元組/秒),吞吐受頻寬限制,頻寬越大,吞吐率的上限才可能越高。
  • PPS,全稱是 Packet Per Second(包/秒),表示以網路包為單位的傳輸速率,一般用來評估系統對於網路的轉發能力。

當然,除了以上這四種基本的指標,還有一些其他常用的效能指標,比如:

  • 網路的可用性,表示網路能否正常通訊;
  • 併發連線數,表示 TCP 連線數量;
  • 丟包率,表示所丟失資料包數量佔所傳送資料組的比率;
  • 重傳率,表示重傳網路包的比例;

檢視網路配置

要想知道網路的配置和狀態,我們可以使用 ifconfig 或者 ip 命令來檢視。這兩個命令功能都差不多,不過它們屬於不同的軟體包,ifconfig 屬於 net-tools軟體包, ip 屬於 iproute2 軟體包,我的印象中 net-tools 軟體包沒有人繼續維護了,而 iproute2 軟體包是有開發者依然在維護,所以更推薦你使用 ip 工具。
學以致用,那就來使用這兩個命令,來檢視網口 eth0 的配置等資訊:

# ifconfig eth0 
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.16.108.119  netmask 255.255.255.0  broadcast 172.16.108.255
        inet6 fe80::5054:ff:fe38:e642  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:38:e6:42  txqueuelen 1000  (Ethernet)
        RX packets 215198056  bytes 21032436157 (19.5 GiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 138828601  bytes 15573459510 (14.5 GiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

# ip -s addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 52:54:00:38:e6:42 brd ff:ff:ff:ff:ff:ff
    inet 172.16.108.119/24 brd 172.16.108.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fe38:e642/64 scope link 
       valid_lft forever preferred_lft forever
    RX: bytes  packets  errors  dropped overrun mcast   
    21032460596 215198294 0       0       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    15573475739 138828738 0       0       0       0 

雖然這兩個命令輸出的格式不盡相同,但是輸出的內容基本相同,比如都包含了 IP 地址、子網掩碼.MAC 地址、閘道器地址、MTU 大小、網口的狀態以及網路包收發的統計資訊,下面就來說說這些資訊,它們都與網路效能有一定的關係。

第一,網口的連線狀態標誌。其實也就是表示對應的網口是否連線到交換機或路由器等裝置,如果ifconfig輸出中看到有RUNNING,或者ip輸出中有 LOWER UP,則說明物理網路是連通的,如果看不到,則表示網口沒有接網線。

第二,MTU 大小。預設值是 1500 位元組,其作用主要是限制網路包的大小,如果 IP 層有一個資料包要傳,而且網路包的長度比鏈路層的 MTU 還大,那麼IP 層就需要進行分片,即把資料包分成若干片,這樣每一片就都小於 MTU。事實上,每個網路的鏈路層 MTU 可能會不一樣,所以你可能需要調大或者調小MTU 的數值。

第三,網口的IP 地址、子網掩碼、MAC地址、閘道器地址。這些資訊必須要配置正確,網路功能才能正常工作。

第四,網路包收發的統計資訊。通常有網路收發的位元組數、包數、錯誤數以及丟包情況的資訊,如果 X(傳送)和RX(接收)部分中 errors、dropped、overruns、carrier 以及 colisions 等指標不為0時則說明網路傳送或者接收出問題了,這些出錯統計資訊的指標意義如下:

  • errors 表示發生錯誤的資料包數,比如校驗錯誤、幀同步錯誤等;
  • dropped 表示丟棄的資料包數,即資料包已經收到了 Ring Buffer(這個緩衝區是在核心記憶體中,更具體一點是在網路卡驅動程式裡),但因為系統記憶體不足等原因而發生的丟包;
  • overruns 表示超限資料包數,即網路接收/傳送速度過快,導致 Ring Buffer 中的資料包來不及處理,而導致的丟包,因為過多的資料包擠壓在 Ring Buffer,這樣 Ring Buffer 很容易就溢位了;
  • carrier 表示發生 carrirer 錯誤的資料包數,比如雙工模式不匹配、物理電纜出現問題等;
  • collisions 表示衝突、碰撞資料包數;

ifconfig 和 ip 命令只顯示的是網口的配置以及收發資料包的統計資訊,而看不到協議棧裡的資訊那接下來就來看看如何檢視協議棧裡的資訊。

檢視socket資訊

我們可以使用netstat或者ss,這兩個命令檢視socket、網路協議棧、網口以及路由表的資訊。

雖然 netstat 與 ss 命令檢視的資訊都差不多,但是如果在生產環境中要檢視這類資訊的時候,儘量不要使用 netstat 命令,因為它的效能不好,在系統比較繁忙的情況下,如果頻繁使用 netstat 命令則會對效能的開銷雪上加霜,所以更推薦你使用效能更好的ss命令。
從下面這張圖,你可以看到這兩個命令的輸出內容:

# -n表示不顯示名字,而是以數字方式顯示ip和埠
# -l表示只顯示LISTEN狀態的socket
# -p表示顯示程序資訊

# netstat -nlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      842/sshd 



# -l 表示只顯示Listen狀態的socket
# -t 表示只顯示tcp連線
# -n 表示不顯示名字,而是以數字方式顯示ip和埠
# -p 表示顯示程序資訊

# ss -ltnp
State      Recv-Q Send-Q                                                Local Address:Port                                                               Peer Address:Port              
LISTEN     0      128                                                               *:22                                                                            *:*                   users:(("sshd",pid=842,fd=3))

可以發現,輸出的內容都差不多,比如都包含了socket的狀態(State)、接收佇列(Recv-Q)、傳送佇列(Send-Q)、本地地址(Local Address)、遠端地址(Foreign Address)、程序 PID 和程序名稱(PID/Program name)等。

接收佇列(Recv-Q)和傳送佇列(Send-Q)比較特殊,在不同的 socket 狀態。它們表示的含義是不同的。
當socket狀態處於Established時:

  • Recv-0 表示 socket 緩衝區中還沒有被應用程式讀取的位元組數;
  • Send-0 表示 socket 緩衝區中還沒有被遠端主機確認的位元組數;

而當socket狀態處於Listen時:

  • Recv-0 表示全連線佇列的長度;
  • Send-Q 表示全連線佇列的最大長度;
    在 TCP 三次握手過程中,當伺服器收到客戶端的 SYN 包後,核心會把該連線儲存到半連線佇列,然後再向客戶端傳送 SYN+ACK 包,接著客戶端會返回 ACK,服務端收到第三次握手的 ACK後,核心會把連線從半連線佇列移除,然後建立新的完全的連線,並將其增加到全連線佇列,等待程序呼叫accept()函式時把連線取出來。

也就說,全連線佇列指的是伺服器與客戶端完了TCP 三次握手後,還沒有被 accept()系統呼叫取走連線的佇列。那對於協議棧的統計資訊,依然還是使用netstat或ss,它們檢視統計資訊的命令如下:

# netstat -s
Ip:
    194576101 total packets received
    18621 forwarded
    0 incoming packets discarded
    141746242 incoming packets delivered
    136457468 requests sent out
Icmp:
    679 ICMP messages received
    0 input ICMP message failed.
    ICMP input histogram:
        destination unreachable: 339
        timeout in transit: 9
        echo requests: 18
        echo replies: 313
    1044 ICMP messages sent
    0 ICMP messages failed
    ICMP output histogram:
        destination unreachable: 374
        echo request: 652
        echo replies: 18
IcmpMsg:
        InType0: 313
        InType3: 339
        InType8: 18
        InType11: 9
        OutType0: 18
        OutType3: 374
        OutType8: 652
Tcp:
    1101687 active connections openings
    22388262 passive connection openings
    65 failed connection attempts
    1361 connection resets received
    18 connections established
    139649288 segments received
    136411978 segments send out
    10506 segments retransmited
    9 bad segments received.
    28284049 resets sent
Udp:
    2064989 packets received
    48 packets to unknown port received.
    0 packet receive errors
    2066536 packets sent
    0 receive buffer errors
    0 send buffer errors
    IgnoredMulti: 31235
UdpLite:
TcpExt:
    17824374 TCP sockets finished time wait in fast timer
    15638 delayed acks sent
    2170 delayed acks further delayed because of locked socket
    Quick ack mode was activated 392 times
    8177072 packet headers predicted
    39935467 acknowledgments not containing data payload received
    9413542 predicted acknowledgments
    612 times recovered from packet loss by selective acknowledgements
    Detected reordering 1033 times using SACK
    Detected reordering 21 times using time stamp
    2 congestion windows fully recovered without slow start
    15 congestion windows partially recovered using Hoe heuristic
    97 congestion windows recovered without slow start by DSACK
    50 congestion windows recovered without slow start after partial ack
    TCPLostRetransmit: 1469
    2 timeouts after SACK recovery
    7 timeouts in loss state
    1631 fast retransmits
    155 retransmits in slow start
    2084 other TCP timeouts
    TCPLossProbes: 8732
    TCPLossProbeRecovery: 49
    87 SACK retransmits failed
    TCPBacklogCoalesce: 87720
    393 DSACKs sent for old packets
    1 DSACKs sent for out of order packets
    5975 DSACKs received
    3 DSACKs for out of order packets received
    59 connections reset due to unexpected data
    1275 connections reset due to early user close
    49 connections aborted due to timeout
    TCPDSACKIgnoredNoUndo: 5085
    TCPSpuriousRTOs: 37
    TCPSackShifted: 348
    TCPSackMerged: 486
    TCPSackShiftFallback: 2931
    TCPRcvCoalesce: 756203
    TCPOFOQueue: 8973
    TCPOFOMerge: 1
    TCPChallengeACK: 22
    TCPSYNChallenge: 22
    TCPSpuriousRtxHostQueues: 37
    TCPAutoCorking: 184636
    TCPFromZeroWindowAdv: 881
    TCPToZeroWindowAdv: 881
    TCPWantZeroWindowAdv: 3108
    TCPSynRetrans: 1632
    TCPOrigDataSent: 50254798
    TCPHystartTrainDetect: 59
    TCPHystartTrainCwnd: 5519
    TCPACKSkippedSeq: 3
    TCPWinProbe: 1
    TCPKeepAlive: 256475
    TCPDelivered: 51360491
    TCPAckCompressed: 6199
IpExt:
    InNoRoutes: 26
    OutMcastPkts: 2
    InBcastPkts: 31235
    InOctets: 16917283081
    OutOctets: 13614894861
    OutMcastOctets: 80
    InBcastOctets: 2459890
    InNoECTPkts: 195484275




# ss -s
Total: 293 (kernel 2549)
TCP:   72 (estab 18, closed 42, orphaned 0, synrecv 0, timewait 38/0), ports 0

Transport Total     IP        IPv6
*         2549      -         -        
RAW       0         0         0        
UDP       2         1         1        
TCP       30        23        7        
INET      32        24        8        
FRAG      0         0         0 

ss命令輸出的統計資訊相比netstat少,ss只顯示已經連線(estab)、關閉(closed)、孤兒(orphaned) socket等簡要統計。
而netstat則有更詳細的網路協議棧資訊,比如上面顯示了TCP 協議的主動連線(active connections openings)、被動連線(passive connection openings)、失敗重試(failed connection attempts)、傳送(segments send out)和接收(segments received)的分段數量等各種資訊。

檢視網路吞吐率和PPS

可以使用sar命令檢視當前網路的吞吐率和 PPS,用法是給 sar 增加-n引數就可以檢視網路的統計資訊,比如

  • sar -n DEV,顯示網口的統計資料;
  • sar -n EDEV,顯示關於網路錯誤的統計資料;
  • sar -n TCP,顯示 TCP 的統計資料;

比如,我透過命令獲取了網口的統計資訊:

# 數字1表示每隔1秒輸出一組資料
# sar -n DEV 1
Linux 5.4.259-1.el7.elrepo.x86_64 (devops03)    09/11/24        _x86_64_        (4 CPU)

20:07:39        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
20:07:40      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:40           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:40         eth0      6.00      2.00      1.79      0.61      0.00      0.00      0.00
20:07:40    veth80c838e      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:40    vethf2f2053      0.00      0.00      0.00      0.00      0.00      0.00      0.00

20:07:40        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
20:07:41      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:41           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:41         eth0      5.00      2.00      0.30      0.82      0.00      0.00      0.00
20:07:41    veth80c838e      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:41    vethf2f2053      0.00      0.00      0.00      0.00      0.00      0.00      0.00

20:07:41        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
20:07:42      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:42           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:42         eth0     11.94      8.96      1.65      2.15      0.00      0.00      0.00
20:07:42    veth80c838e      0.00      0.00      0.00      0.00      0.00      0.00      0.00
20:07:42    vethf2f2053      0.00      0.00      0.00      0.00      0.00      0.00      0.00

Average:        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s
Average:      docker0      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:         eth0      7.12      3.75      1.19      1.08      0.00      0.00      0.00
Average:    veth80c838e      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:    vethf2f2053      0.00      0.00      0.00      0.00      0.00      0.00      0.00

它們的含義:

  • rxpck/s 和 txpck/s 分別是接收和傳送的 PPS,單位為包/秒。
  • rxkB/s 和 txkB/s 分別是接收和傳送的吞吐率,單位是KB/秒。
  • rxcmp/s 和 txcmp/s分別是接收和傳送的壓縮資料包數,單位是包/秒。

對於頻寬,我們可以使用ethtool命令來查詢,它的單位通常是 Gb/s或者 Mb/s,不過注意這裡小寫字母b,表示位元而不是位元組。我們通常提到的千兆網路卡、萬兆網路卡等,單位也都是位元(bit)。如下你可以看到,eth0網路卡就是一個千兆網路卡:

# ethtool eth0|grep Speed
        Speed: 10000Mb/s

檢視連通性和延時

要測試本機與遠端主機的連通性和延時,通常是使用 ping 命令,它是基於 ICMP 協議的,工作在網路層。
比如,如果要測試本機到www.baidu.com的連通性和延時:

# -c 表示傳送 3 次 ICMP 包
ping -c 3 -w 3 www.baidu.com
PING www.a.shifen.com (180.101.50.242) 56(84) bytes of data.
64 bytes from 180.101.50.242 (180.101.50.242): icmp_seq=1 ttl=50 time=6.26 ms
64 bytes from 180.101.50.242 (180.101.50.242): icmp_seq=2 ttl=50 time=6.24 ms
64 bytes from 180.101.50.242 (180.101.50.242): icmp_seq=3 ttl=50 time=6.23 ms

--- www.a.shifen.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2020ms
rtt min/avg/max/mdev = 6.234/6.247/6.262/0.091 ms

顯示的內容主要包含icmp_seq(ICMP序列號)、TTL(生存時間,或者跳數)以及 time(往返延時),而且最後會彙總本次測試的情況,如果網路沒有丟包,packet loss的百分比就是0。

不過,需要注意的是,ping不通伺服器並不代表HTTP請求也不通,因為有的伺服器的防火牆是會禁用ICMP協議的。

相關文章