34丨關於Linux網路,你必須知道這些(下)
阿新 • • 發佈:2020-11-22
上一節,學習了 Linux 網路的基礎原理。簡單回顧一下,Linux 網路根據 TCP/IP 模型,構建其網路協議棧。TCP/IP 模型由應用層、傳輸層、網路層、網路介面層等四層組成,這也是 Linux 網路棧最核心的構成部分。
應用程式通過套接字介面傳送資料包時,先要在網路協議棧中從上到下逐層處理,然後才最終送到網絡卡傳送出去;而接收資料包時,也要先經過網路棧從下到上的逐層處理,最後送到應用程式。
瞭解 Linux 網路的基本原理和收發流程後,你肯定迫不及待想知道,如何去觀察網路的效能情況。具體而言,哪些指標可以用來衡量 Linux 的網路效能呢?
效能指標
實際上,我們通常用頻寬、吞吐量、延時、PPS(Packet Per Second)等指標衡量網路的效能。- 頻寬,表示鏈路的最大傳輸速率,單位通常為 b/s (位元 / 秒)。
- 吞吐量,表示單位時間內成功傳輸的資料量,單位通常為 b/s(位元 / 秒)或者 B/s(位元組 / 秒)。吞吐量受頻寬限制,而吞吐量 / 頻寬,也就是該網路的使用率。
- 延時,表示從網路請求發出後,一直到收到遠端響應,所需要的時間延遲。在不同場景中,這一指標可能會有不同含義。比如,它可以表示,建立連線需要的時間(比如 TCP 握手延時),或一個數據包往返所需的時間(比如 RTT)。
- PPS,是 Packet Per Second(包 / 秒)的縮寫,表示以網路包為單位的傳輸速率
網路配置
分析網路問題的第一步,通常是檢視網路介面的配置和狀態。你可以使用 ifconfig 或者 ip 命令,來檢視網路的配置。我個人更推薦使用 ip 工具,因為它提供了更豐富的功能和更易用的介面。 ifconfig 和 ip 分別屬於軟體包 net-tools 和 iproute2,iproute2 是 net-tools 的下一代。通常情況下它們會在發行版中預設安裝。但如果你找不到 ifconfig 或者 ip 命令,可以安裝這兩個軟體包。 以網路介面 eth0 為例,你可以執行下面的兩個命令,檢視它的配置和狀態:你可以看到,ifconfig 和 ip 命令輸出的指標基本相同,只是顯示格式略微不同。比如,它們都包括了網路介面的狀態標誌、MTU 大小、IP、子網、MAC 地址以及網路包收發的統計資訊。 這些具體指標的含義,在文件中都有詳細的說明,不過,這裡有幾個跟網路效能密切相關的指標,需要你特別關注一下。 第一,網路介面的狀態標誌。ifconfig 輸出中的 RUNNING ,或 ip 輸出中的 LOWER_UP ,都表示物理網路是連通的,即網絡卡已經連線到了交換機或者路由器中。如果你看不到它們,通常表示網線被拔掉了。 第二,MTU 的大小。MTU 預設大小是 1500,根據網路架構的不同(比如是否使用了 VXLAN 等疊加網路),你可能需要調大或者調小 MTU 的數值。 第三,網路介面的 IP 地址、子網以及 MAC 地址。這些都是保障網路功能正常工作所必需的,你需要確保配置正確。 第四,網路收發的位元組數、包數、錯誤數以及丟包情況,特別是 TX 和 RX 部分的 errors、dropped、overruns、carrier 以及 collisions 等指標不為 0 時,通常表示出現了網路 I/O 問題。其中:$ ifconfig eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 10.240.0.30 netmask 255.240.0.0 broadcast 10.255.255.255 inet6 fe80::20d:3aff:fe07:cf2a prefixlen 64 scopeid 0x20<link> ether 78:0d:3a:07:cf:3a txqueuelen 1000 (Ethernet) RX packets 40809142 bytes 9542369803 (9.5 GB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 32637401 bytes 4815573306 (4.8 GB) 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 mq state UP group default qlen 1000 link/ether 78:0d:3a:07:cf:3a brd ff:ff:ff:ff:ff:ff inet 10.240.0.30/12 brd 10.255.255.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::20d:3aff:fe07:cf2a/64 scope link valid_lft forever preferred_lft forever RX: bytes packets errors dropped overrun mcast 9542432350 40809397 0 0 0 193 TX: bytes packets errors dropped carrier collsns 4815625265 32637658 0 0 0 0
- errors 表示發生錯誤的資料包數,比如校驗錯誤、幀同步錯誤等;
- dropped 表示丟棄的資料包數,即資料包已經收到了 Ring Buffer,但因為記憶體不足等原因丟包;
- overruns 表示超限資料包數,即網路 I/O 速度過快,導致 Ring Buffer 中的資料包來不及處理(佇列滿)而導致的丟包;
- carrier 表示發生 carrirer 錯誤的資料包數,比如雙工模式不匹配、物理電纜出現問題等;
- collisions 表示碰撞資料包數。
套接字資訊
ifconfig 和 ip 只顯示了網路介面收發資料包的統計資訊,但在實際的效能問題中,網路協議棧中的統計資訊,我們也必須關注。你可以用 netstat 或者 ss ,來檢視套接字、網路棧、網路介面以及路由表的資訊。 我個人更推薦,使用 ss 來查詢網路的連線資訊,因為它比 netstat 提供了更好的效能(速度更快)。 比如,你可以執行下面的命令,查詢套接字資訊:# head -n 3 表示只顯示前面 3 行
# -l 表示只顯示監聽套接字
# -n 表示顯示數字地址和埠 (而不是名字)
# -p 表示顯示程序資訊
$ netstat -nlp | head -n 3
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN 840/systemd-resolve
# -l 表示只顯示監聽套接字
# -t 表示只顯示 TCP 套接字
# -n 表示顯示數字地址和埠 (而不是名字)
# -p 表示顯示程序資訊
$ ss -ltnp | head -n 3
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 128 127.0.0.53%lo:53 0.0.0.0:* users:(("systemd-resolve",pid=840,fd=13))
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1459,fd=3))
netstat 和 ss 的輸出也是類似的,都展示了套接字的狀態、接收佇列、傳送佇列、本地地址、遠端地址、程序 PID 和程序名稱等。
其中,接收佇列(Recv-Q)和傳送佇列(Send-Q)需要你特別關注,它們通常應該是 0。當你發現它們不是 0 時,說明有網路包的堆積發生。當然還要注意,在不同套接字狀態下,它們的含義不同。
當套接字處於連線狀態(Established)時,
- Recv-Q 表示套接字緩衝還沒有被應用程式取走的位元組數(即接收佇列長度)。
- 而 Send-Q 表示還沒有被遠端主機確認的位元組數(即傳送佇列長度)。
- Recv-Q 表示 syn backlog 的當前值。
- 而 Send-Q 表示最大的 syn backlog 值。
協議棧統計資訊
類似的,使用 netstat 或 ss ,也可以檢視協議棧的資訊:$ netstat -s
...
Tcp:
3244906 active connection openings
23143 passive connection openings
115732 failed connection attempts
2964 connection resets received
1 connections established
13025010 segments received
17606946 segments sent out
44438 segments retransmitted
42 bad segments received
5315 resets sent
InCsumErrors: 42
...
$ ss -s
Total: 186 (kernel 1446)
TCP: 4 (estab 1, closed 0, orphaned 0, synrecv 0, timewait 0/0), ports 0
Transport Total IP IPv6
* 1446 - -
RAW 2 1 1
UDP 2 2 0
TCP 4 3 1
...
這些協議棧的統計資訊都很直觀。ss 只顯示已經連線、關閉、孤兒套接字等簡要統計,而 netstat 則提供的是更詳細的網路協議棧資訊。
比如,上面 netstat 的輸出示例,就展示了 TCP 協議的主動連線、被動連線、失敗重試、傳送和接收的分段數量等各種資訊。
網路吞吐和 PPS
接下來,我們再來看看,如何檢視系統當前的網路吞吐量和 PPS。在這裡,我推薦使用我們的老朋友 sar,在前面的 CPU、記憶體和 I/O 模組中,我們已經多次用到它。 給 sar 增加 -n 引數就可以檢視網路的統計資訊,比如網路介面(DEV)、網路介面錯誤(EDEV)、TCP、UDP、ICMP 等等。執行下面的命令,你就可以得到網路介面統計資訊:# 數字 1 表示每隔 1 秒輸出一組資料
$ sar -n DEV 1
Linux 4.15.0-1035-azure (ubuntu) 01/06/19 _x86_64_ (2 CPU)
13:21:40 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
13:21:41 eth0 18.00 20.00 5.79 4.25 0.00 0.00 0.00 0.00
13:21:41 docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
13:21:41 lo 0.00 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 分別是接收和傳送的壓縮資料包數,單位是包 / 秒。
- %ifutil 是網路介面的使用率,即半雙工模式下為 (rxkB/s+txkB/s)/Bandwidth,而全雙工模式下為 max(rxkB/s, txkB/s)/Bandwidth。
$ ethtool eth0 | grep Speed
Speed: 1000Mb/s
連通性和延時
最後,我們通常使用 ping ,來測試遠端主機的連通性和延時,而這基於 ICMP 協議。比如,執行下面的命令,你就可以測試本機到 114.114.114.114 這個 IP 地址的連通性和延時:# -c3 表示傳送三次 ICMP 包後停止
$ ping -c3 114.114.114.114
PING 114.114.114.114 (114.114.114.114) 56(84) bytes of data.
64 bytes from 114.114.114.114: icmp_seq=1 ttl=54 time=244 ms
64 bytes from 114.114.114.114: icmp_seq=2 ttl=47 time=244 ms
64 bytes from 114.114.114.114: icmp_seq=3 ttl=67 time=244 ms
--- 114.114.114.114 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 244.023/244.070/244.105/0.034 ms
ping 的輸出,可以分為兩部分。
- 第一部分,是每個 ICMP 請求的資訊,包括 ICMP 序列號(icmp_seq)、TTL(生存時間,或者跳數)以及往返延時。
- 第二部分,則是三次 ICMP 請求的彙總。