我们简单说一下Linux的网络子系统
CPU 内存 以及IO 都是Linux的核心功能
网络是一种将不同的计算机连接到一起的技术,本质上是一种进程间通信的方式,特别是跨系统的进程间通信,必须要通过网络
传统上来说,网络模型分为了7层架构,或者说4层架构
七层中分为了
应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
在4层架构中,是Linux的常见表示网路架构
分为了应用层,传输层,网络层,网路接口层四层
应用层负责 进行提供网络接口给应用程序,比如HTTP FTP DNS
传输层负责 端到端的传输 TCP及UDP等
网络层 网络包的封装 寻址 以及路由 提供IP以及ICMP等
网络接口层 网络包在物理网络中的传输,比如MAC寻址 错误侦测 网卡传输
七层和四层架构的区别,基本可以总结为下图
在有了对应的TCP/IP的模型之后,进行网络传输的时候,数据包就会按照协议栈,对上层的数据进行逐层封装,发给下一层
基本上的封装如下
传输层在应用程序前面加了TCP头
网络层在TCP之前加了IP头
网络接口,则加了帧头及帧尾
在三层中,限制了MTU的大小,在网络层中分片,保证分片后的IP不超过MTU的大小
MTU的默认值是1500
一旦网络包超过了MTU的大小,就会在网络层中分片
然后,我们说一下最下层的网卡,即物理层,网卡在启动的时候,通过内核的网卡驱动注册到系统中,然后在网络收发过程中,内核通过中断和网卡进行交互
结合之前提到的Linux网络栈来看,网络包的处理分为硬中断和软中断
硬中断只处理最核心的网卡数据读取和发送,协议栈中的大部分逻辑,放在软中断中处理
Linux网络收发流程
首先是接收的流程,当一个网络帧到了网卡之后,网卡通过DMA的方式放入到收包队列中,然后通过硬中断,告诉中断处理程序收到了网络包
接着,网卡处理程序会为网络帧分配数据结构,让其拷贝到sk_buff缓冲区中,通过软中断通知内核收到了新的网络帧
接下来,内核协议栈从缓冲区中取出网络帧,通过网络协议栈,从上到下的处理这个网络帧
整体的流程如下
对应的发送流程,基本如下
网络包的接受流程对应的就是发送流程
其实就是利用Socket API发送网络包
这样触发了一个系统调用,陷入了内核态的套接字层中,套接字层会将数据包放入到Socket发送缓冲区中
然后网络协议栈从Socket发送缓冲区中,获取到数据包,按照TCP/IP栈,从上到下的处理
处理完成之后,有软中断通知驱动程序,告诉内核发包队列中有新的网络帧需要发送
最后驱动程序通过DMA,从发包队列中读出了网络帧,通过物理网卡发出去
最后整理下网卡发送和接受报文的过程,
内核分配了一个主内存地址段 DMA缓冲区,网卡设备可以通过DMA缓冲区读写数据
当来了一个网络包,网卡将网络包写入DMA缓冲区,写完通知CPU产生硬中断
硬中断处理程序锁定当前的DMA缓冲区,然后将网络包拷贝到另一个内存区,清空并解锁当前DMA缓冲区,通知软中断去处理网络包
我们说完了整体的Linux网络架构和原理,应用程序通过套接字接口发送数据包的时候,通过网络协议栈从上到下进行逐层处理,最终通过网卡发送出去,接收网络包则是一套相反的流程,了解了这些,下一步们则是需要知道哪些的指标可以衡量Linux的网络协议
常见的指标,包含
带宽 链路的最大传输速率,单位为b/s
吞吐量,单位时间传输成功的数据量,单位为b/s或者B/s -> 吞吐量/带宽,就是网络的使用率
延时,网络包从发出到对应的响应的时间,一般指的是RTT 数据包往返的时间
PPS 网络包为单位的传输效率,PPS通常用于评估网络转发能力
除此外,网络性能还有 网络可用性 并发连接数 丢包率 重传率也是常用的性能指标
对于网络问题分析的第一步,就是查看网络接口的配置和状态,可以使用ifconfig ip命令
ifconfig和ip分别属于软件包 net-tools 和 iproute2 , iproute2是nettools的下一代,通常情况下会在发行版中默认安装
以网络接口eth0为例,可以运行如下的命令,获取对应的配置和状态
$ 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 |
两者输出类似,只是格式不同,他们都包括了网络接口的状态标志 MTU大小 IP 子网 MAC地址和网络包的收发统计信息
里面包含几个和网络密切相关的指标,包括如下
第一,网络接口的标志状态,ifconfig中的RUNNING ip输出汇总的LOWER_UP,说明物理网络是连通的,网卡已经介入了交换机或者路由器中,如果看不到,说明网线被拔掉了
MTU的大小,MTU默认是1500,根据网络架构,可能需要调大或调小MTU的数值
网络接口的IP地址 子网和MAC地址
网络收发的字节数,包数,错误数以及丢包的请求,包括 errors dropped overruns carrier
collisions 不为0,表示出现了网络IO问题
errors 包括错误的包数
dropped表示丢弃的包数
overruns 超限数据包,即网络IO速度过快,导致RingBuffer来不及处理而丢包
carrier 表示carrier错误的包数,比如物理电缆问题等
collsions 碰撞包数
套接字信息
ifconfig和ip只显示了网络接口收发数据的统计信息
实际性能之中,netstat或者ss,都可以用来查看套接字,网络栈 网络接口以及路由表信息
ss来查看网路连接
# 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的输出都是类似的
其中的重要指标是 接受队列Recv-Q和发送队列 Send-Q,通常是0,如果不是0,说明有网络包的堆积
在链接的不同状态,会有不同的含义
Established的时候,Recv-Q会表示套接字缓冲还没有被应用程序取走的字节数
Send-Q表示还没有被远端主机确认的字节数
而Listening的时候,
Recv-Q表示全连接队列的长度
Send-Q表示全连接队列的最大长度
然后查看协议栈相关统计信息
使用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
sar则可以直接查看.只需要加上-n的参数节课
获取对应的信息,输出的指标比较多,比如下面的信息
# 数字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
Bandwidth 可以使用ethtool查询,单位是Gb/s 或者是Mb/s 都是比特而不是字节
最后就是ping
ping 一个地址,可以获得两部分信息
可以获取对应的ICMP 的 ping的信息
本次,我们说了,如何使用带宽 吞吐量 延时等指标,获得衡量网络的性能
可以使用ifconfig netstat ss sar ping等工具,进行查看网路性能