这篇文章上次修改于 899 天前,可能其部分内容已经发生变化,如有疑问可询问作者。
1 网络模型
TCP/IP 模型:
- 应用层,负责向用户提供一组应用程序,如 HTTP、FTP、DNS 等。
- 传输层,负责端到端的通信,如 TCP、UDP 等。
- 网络层,负责网络包的封装、寻址和路由,如 IP、ICMP 等。
- 网络接口层,负责网络包在物理网络中的传输,如 MAC 寻址,错误侦测和通过网卡传输网络帧等。
2 Linux 网络栈
进行网络传输时,会按照协议栈对上层传过来的数据包封装上本层的头,然后传递给下一层:
- 传输层会在应用数据前添加 TCP 头。
- 网络层在 TCP 数据包前添加 IP 头。
- 网络接口层在 IP 数据包前后添加帧头和帧尾。
MTU 为网络接口配置的最大传输单元,规定了最大 IP 包大小,超过该大小会被分片。
Linux 网络栈:
- 最上层的应用需要通过系统调用与套接字接口交互。
- 套接字下面,是传输层、网络层和网络接口层。
- 最底层,是网卡驱动和物理网卡设备。
3 Linux 网络包收发流程
3.1 网络包接收流程
- 当网络帧到达网卡后,网卡通过 DMA 方式将网络包放到收包队列中。然后通过硬中断通知中断处理程序收到了网络包。
- 网络中断处理程序会为网络帧分配内核数据结构(sk_buff),并将其拷贝到 sk_buff 缓冲区中。然后通过软中断通知内核收到了新的网络帧。
网络协议栈从缓冲区中取出网络帧,并通过网络协议栈从下到逐层处理:内核从缓冲区中取出网络帧,并通过网络协议栈从下到逐层处理:
- 链路层检查报文的合法性,找出上层协议的类型(IPV4 或 IPV6),然后去掉帧头和帧尾,交给网络层。
- 网络层取出 IP 头,找出上层协议类型(UDP 或 TCP),判断是需要转发还是还是交给上层处理。如果是交给上层处理,则去掉 IP 头,交给传输层处理。
- 传输层取出 TCP 或 UDP 头后,根据 <源 IP,源端口,目的 IP,目的端口> 找到对应的 Socket,并将数据拷贝到 Socket 的接收缓存中。
3.2 网络包发送流程
- 应用程序调用 Socket API 发送网络包。该系统调用会陷入到内核态的套接字层中。套接字层会将数据包放到 Socket 的发送缓冲区中。
网络协议栈从 Socket 发送缓冲区中取出数据包,再按照 TCP/IP 协议栈从上到下逐层处理。比如
- 传输层和网络层分别为数据包添加 TCP 头和 IP 头,执行路由查找确认下一跳的 IP,并按照 MTU 大小进行分片。
- 分片后的网络包送到网络接口层,进行 MAC 寻址,然后添加帧头和帧尾,放到发包队列中。
- 会有软中断通知驱动程序,发包队列中有新的网络包需要发送。
- 驱动程序通过 DMA,从发包队列读出网络帧,并通过物理网卡发送出去。
4 性能指标
- 带宽,链路最大传输速率,单位通常为 b/s
- 吞吐量,单位时间内成功传输的数据量,单位通常为 b/s 或 B/s
- 延迟,从网络请求发出后,到收到远端响应的时间。
- PPS,以网络包为单位的传输速率。通常用来评估网络的转发能力。
- 其他,如网络可用性、并发连接数、丢包率、重传率。
5 网络配置
$ 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
- 网络接口状态标志。RUNNING 表示网络是连通的,即网卡已经查到了交换机或路由器中。
- MTU 大小,默认是 1500。
- 网络的 IP 地址、子网及 MAC 地址。
网络的收发字节数、包数、错误数及丢包情况。RX、TX 的 errors、dropped、overruns、carrier、collisions 等不为 0 时,通常表示出现了网络 I/O 问题。
- erros,表示发生错误包数,如校验错误、帧同步错误等。
- dropped,表示丢弃的网络包数,即数据已经收到了 Ring Buffer 中,但因内存不足等原因丢弃。
- overruns,表示超限网络包数,即网络 I/O 过快,Ring Buffer 中的数据包来不及处理而导致的丢包。
- carrier,如因双工模式不匹配,物理电缆出现问题等。
- collisions,碰撞包数。
6 套接字信息
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))
当套接字处于 Established 状态时:
- Recv-Q 表示接收队列长度。套接字缓冲区中还没有被应用程序取走的字节数。
- Send-Q 表示发送队列长度。还没有被远端主机确认的字节数。
当套接字处于 Listening 状态时:
- Recv-Q 表示全连接队列长度。完成 TCP 三次握手的连接数。
- Send-Q 表示全连接队列最大长度。
7 协议栈统计信息
$ 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 还提供了主动连接、被动连接、失败重试、发送和接收的分段数量等信息。
8 网络吞吐和 PPS
# 数字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,单位为 包/s
- txcmp/s、rxcmp/s 分别为发送、接收的压缩数据包数,单位为包/s
- %ftuil 为网口利用率,单工模式下为(rxkB/s + txkB/s) / Bandwith,全双工模式下为 max(rxkB/s, txkB/s) / Bandwith
查看 Bandwith:
$ ethtool eth0 | grep Speed
Speed: 1000Mb/s
9 连通性和延迟
# -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
包括 ICMP 序列号,TTL(生存时间或跳数)和往返延时。
参考
倪朋飞. Linux 性能优化实战.
没有评论