Linux网络性能指标

性能指标

  • 带宽,表示链路的最大传输速率,单位通常为 b/s(比特/秒)
  • 吞吐量,表示单位时间内成功传输的数据量,单位通常为 b/s(比特/秒)或者 B/s(字节/秒)。吞吐量受带宽限制,而吞吐量/带宽,也就是该网络的使用率
  • 延时,表示从网络请求发出后,一直到收到远端响应,所需要的时间延迟。在不同场景中,这一指标可能会有不同的涵义。比如,它可以表示,建立连接需要的时间(比如 TCP 握手延时),或一个数据包往返所需的时间(比如 RTT)
  • PSS,是 Packet Per Second(包/秒)的缩写,表示以网络包为单位的传输速率。PSS 通常用来评估网络的转发能力,比如硬件交换机,通常可以达到线性转发(即 PPS 可以达到或者接近理论最大值)。而基于 Linux 服务器的转发,则容易受网络包大小的影响

另外,网络的可用性(网络能否正常通信)、并发连接数(TCP 连接数量)、丢包率(丢包百分比)、重传率(重新传输的网络包比例)等也是常用的性能指标。

网络配置

使用命令 ifconfig 或者 ip 查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$ ifconfig eth1
eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 9.134.194.74 netmask 255.255.248.0 broadcast 9.134.199.255
ether 52:54:00:82:12:e8 txqueuelen 1000 (Ethernet)
RX packets 70297502 bytes 34143392231 (31.7 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 78816203 bytes 45528648722 (42.4 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

$ ip -s addr show dev eth1
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP qlen 1000
link/ether 52:54:00:82:12:e8 brd ff:ff:ff:ff:ff:ff
inet 9.134.194.74/21 brd 9.134.199.255 scope global eth1
valid_lft forever preferred_lft forever
RX: bytes packets errors dropped overrun mcast
34143407013 70297654 0 0 0 0
TX: bytes packets errors dropped carrier collsns
45528723929 78816328 0 0 0 0

第一,网络接口的状态标志。ifconfig 输出 RUNNING,或者 ip 输出中的 LOWER_UP,都表示物理网络是连通,即网卡已经连接到了交换机或者路由器中。如果你看不到它们,通常表示网线被拔掉了。

第二,MTU 的大小。MTU 默认大小是 1500,根据网络架构的不同(比如是否使用了 VXLAN 等叠加网络),你可能需要调大或者调小 MTU 的数值。

第三,网络接口的 IP 地址、子网以及 MAC 地址。这些地址都是保障网络功能正常工作所必须的,你需要确保配置正确。

第四,网络收发的字节数、包数、错误数以及丢包情况,特别是 TX 和 RX 部分的 errors、dropped、overruns、carrier 以及 collisions 等指标不为 0 时,通常表示出现了网络 I/O 问题。其中:

  • errors 表示发生错误的数据包数,比如校验错误、帧同步错误等
  • dropped 表示丢弃的数据包数,即数据包已经收到了 Ring Buffer,但因为内存不足等原因丢包
  • overruns 表示超限数据丢包数,即网络 I/O 速度过快,导致 Ring Buffer 中的数据包来不及处理(队列满)而导致的丢包
  • carrier 表示发生 carrirer 错误的数据报数,比如双工模式不匹配、物理电缆出现问题等
  • collisions 表示碰撞数据包数

嵌套字信息

使用 netstat 或 ss 来表示嵌套字、网络栈、网络接口以及路由表的信息

1
2
3
4
5
6
7
8
9
$ 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.1:10248 0.0.0.0:* LISTEN 624565/kubelet

$ ss -ltnp | head -n 3
State Recv-Q Send-Q Local Address:Port Peer Address:Port
LISTEN 0 65535 127.0.0.1:10248 *:* users:(("kubelet",pid=624565,fd=29))
LISTEN 0 65535 127.0.0.1:10249 *:* users:(("kube-proxy",pid=624952,fd=12))

其中,接收队列(Recv-Q)和发送队列(Send-Q)需要关注,它们通常是 0。当你发现它们不是 0 时,说明有网络包的堆积发生

当嵌套字处于连接状态(Established)时,

  • Recv-Q 表示嵌套字缓冲还没有被应用程序取走的字节数(即接收队列长度)
  • Send-Q 表示还没有被远端主机确认的字节数(即发送队列长度)

当嵌套字处于监听状态(Listening)时,

  • Recv-Q 表示当前全连接队列(accept 队列)长度
  • Send-Q 表示全连接队列的最大长度

协议栈统计信息

使用 netstat 或 ss 命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
$ netstat -s
Ip:
11236847787 total packets received
76906 forwarded
0 incoming packets discarded
10964584370 incoming packets delivered
10948611259 requests sent out
448 outgoing packets dropped
4 dropped because of missing route
Icmp:
37370022 ICMP messages received
158 input ICMP message failed.
ICMP input histogram:
destination unreachable: 141016
echo requests: 20256273
echo replies: 16972733
...

[root@pudding-161 ~]# ss -s
Total: 1434 (kernel 1816)
TCP: 1144 (estab 894, closed 164, orphaned 0, synrecv 0, timewait 158/0), ports 0

Transport Total IP IPv6
* 1816 - -
RAW 2 1 1
UDP 13 7 6
TCP 980 349 631
INET 995 357 638
FRAG 0 0 0

网络吞吐 和 PPS

使用 sar 命令,加上 -n 参数,可以查看网络的统计信息,比如网络接口(DEV)、网络接口错误(EDEV)、TCP、UDP、ICMP 等

1
2
3
4
5
6
7
8
$ sar -n DEV 1
Linux 3.10.0-957.el7.x86_64 (xxx) 06/18/2025 _x86_64_ (8 CPU)

07:20:42 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s
07:20:43 PM dummy0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
07:20:43 PM eth0 695.00 663.00 6938.75 3796.65 0.00 0.00 0.00
07:20:43 PM lo 112.00 112.00 39.30 39.30 0.00 0.00 0.00
07:20:43 PM kube-ipvs0 0.00 0.00 0.00 0.00 0.00 0.00 0.00
  • rxpck/s 和 txpck/s 分别是接收和发送的 PPS,单位为包/秒
  • rxkB/s 和 txkB/s 分别是接收和发送的吞吐量,单位是 KB/s
  • rxcmp/s 和 txcmp/s 分别是接收和发送的压缩数据包数,单位是包/秒

带宽可以用 ethtool 来查询,它的单位通常是 Gb/s 或者 Mb/s(千兆网卡或者万兆网卡的单位都是 bit)

1
2
$ ethtool enp4s0f0 | grep Speed
Speed: 1000Mb/s

连通性和延时

使用命令 ping,来测试远程主机的连通性和延时(基于 ICMP 协议)

如下,测试本机到 baidu.com 这个地址的连通性和延时

1
2
3
4
5
6
7
8
9
$ ping -c3 baidu.com
PING baidu.com (182.61.201.211) 56(84) bytes of data.
64 bytes from 182.61.201.211 (182.61.201.211): icmp_seq=1 ttl=49 time=29.1 ms
64 bytes from 182.61.201.211 (182.61.201.211): icmp_seq=2 ttl=49 time=27.2 ms
64 bytes from 182.61.201.211 (182.61.201.211): icmp_seq=3 ttl=49 time=27.8 ms

--- baidu.com ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 27.280/28.097/29.158/0.785 ms

ping 的输出,可以分为两部分:

  • 每个 ICMP 请求的信息,包括 ICMP 序列号(icmp_seq)、TTL(生存时间,或者跳数)以及往返延时
  • 三次 ICMP 请求的汇总

C10K和C100K问题

C10K

C10K 代表同时处理 10000 个请求

从资源上来说,对 2GB 内存和千兆网卡的服务器来说,同时处理 10000 个请求,只要每个请求处理占用不到 200KB(2GB/10000)的内存和 100Kbit(1000Mbit/10000)的网络带宽就可以。

从软件上来看,主要是网络 I/O 模型的问题,在 C10K 之前,Linux 主要是同步阻塞的方式,每个请求都分配一个进程或者线程,而 10000 个进程或者线程的调度、上下文切换和内存,都可能成为瓶颈。

需要解决的问题:

  • 怎样在一个线程内处理多个请求,也就是要在一个线程内响应多个网络 I/O?

I/O 模型优化

异步、非阻塞 I/O 的思路:I/O 多路复用

两种 I/O 时间通知的方式:水平触发和边缘触发
水平触发:只要文件描述符可以非阻塞地执行 I/O,就会触发通知。也就是说,应用程序可以随时检查文件描述符地状态,然后再根据状态,进行 I/O 操作。
边缘触发:只有在文件描述符的状态发生改变(也就是 I/O 请求达到)时,才会发送一次通知。这时候,应用程序需要尽可能多地执行 I/O,知道无法继续读写,才可以停止。如果 I/O 没执行完,或者因为某种原因没来得及处理,那么这次通知也就丢失了

  • 第一种,使用非阻塞 I/O 和水平触发通知,比如使用 select 或者 poll
  • 第二种,使用非阻塞 I/O 和边缘触发通知,比如 epoll(在 select 和 poll 基础上进行优化)
  • 第三种,使用异步 I/O(Asynchronous I/O,简称为 AIO)

工作模型优化

I/O 多路复用有两种主要的工作模式:

第一种:主进程 + 多个 worker 子进程(比如 nginx),主要流程是:

  • 主进程执行 bind() + listen() 后,创建多个子进程;
  • 在每个子进程中,都通过 accept() 或 epoll_wait() ,来处理相同的套接字

示意图