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 的配置等信息:
虽然这两个命令输出的格式不尽相同,但是输出的内容基本相同,⽐如都包含了 IP 地址、⼦⽹掩码、MAC 地址、⽹关地址、MTU 大小、⽹⼝的状态以及⽹路包收发的统计信息,下⾯就来说说这些信息,它们都与⽹络性能有⼀定的关系。
-
网口的连接状态标志:表示对应的⽹⼝是否连接到交换机或路由器等设备,如果
ifconfig 输出中看到有 RUNNING ,或者 ip 输出中有 LOWER_UP ,则说明物理⽹路是连通的,如果看不到,则表示网口没有接网线。
-
MTU 大小:默认值是 1500 字节,其作⽤主要是限制⽹络包的⼤⼩,如果 IP 层有⼀个数据报要传,⽽且数据帧的⻓度⽐链路层的 MTU 还⼤,那么 IP 层就需要进⾏分⽚,即把数据报分成⼲⽚,这样每⼀⽚就都⼩于 MTU。事实上,每个⽹络的链路层 MTU 可能会不⼀样,所以你可能需要调⼤或者调小 MTU 的数值
-
网口的 IP 地址、⼦⽹掩码、MAC 地址、⽹关地址。这些信息必须要配置正确,⽹络功能才能正常⼯作。
-
网路包收发的统计信息:通常有⽹络收发的字节数、包数、错误数以及丢包情况的信息,如果 TX(发送) 和 RX(接收) 部分中 errors、dropped、overruns、carrier 以及 collisions 等指标不为 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 命令。
可以发现,输出的内容都差不多, ⽐如都包含了 socket 的状态(State)、接收队列(Recv-Q)、发送队列(Send-Q)、本地地址(Local Address)、远端地址(Foreign Address)、进程 PID 和进程名称 (PID/Program name)等。
接收队列(Recv-Q)和发送队列(Send-Q)比较特殊,在不同的 socket 状态。它们表示的含义是不同的。
当 socket 状态处于 Established 时:
- Recv-Q 表示 socket 缓冲区中还没有被应⽤程序读取的字节数;
- Send-Q 表示 socket 缓冲区中还没有被远端主机确认的字节数;
当 socket 状态处于 Listen 时:
- Recv-Q 表示全连接队列的⻓度;
- Send-Q 表示全连接队列的最⼤⻓度;
在 TCP 三次握⼿过程中,当服务器收到客户端的 SYN 包后,内核会把该连接存储到半连接队列, 然后再向客户端发送 SYN+ACK 包,接着客户端会返回 ACK,服务端收到第三次握⼿的 ACK 后,内核会把连接 从半连接队列移除,然后创建新的完全的连接,并将其增加到全连接队列 ,等待进程调⽤ accept() 函数时把连接取出来。
也就说,全连接队列指的是服务器与客户端完了 TCP 三次握⼿后,还没有被 accept() 系统调⽤取⾛连接的队列。
那对于协议栈的统计信息,依然还是使⽤ netstat 或 ss ,它们查看统计信息的命令如下:
ss 命令输出的统计信息相⽐ netsat ⽐较少, 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 的统计数据;
⽐如,我通过 sar 命令获取了网口的统计信息:
它们的含义:
- 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: 1000Mb/s
五、如何查看连通性和延时?
要测试本机与远程主机的连通性和延时,通常是使⽤ ping 命令,它是基于 ICMP 协议的,⼯作在网络层。
⽐如,如果要测试本机到 192.168.12.20 IP 地址的连通性和延时:
显示的内容主要包含 icmp_seq (ICMP 序列号)、 TTL (⽣存时间,或者跳数)以及 time (往返延时),⽽且最后会汇总本次测试的情况,如果⽹络没有丢包, packet loss 的百分⽐就是 0
不过,需要注意的是,ping 不通服务器并不代表 HTTP 请求也不通,因为有的服务器的防⽕墙是会禁⽤ ICMP 协议的。
学自小林coding所著的《图解系统》,侵删