网络基准测试以及监控网络指标

Linux 网络收发流程

Linux 网络栈
image.png

Linux 实际按照 TCP/IP 模型,实现了网络协议栈。在进行网络传输时,数据包就会按照协议栈,对上一层发来的数据进行逐层处理;然后封装上该层的协议头,再发送给下一层。

image.png
网络包的接收

当一个网络帧到达网卡后,网卡会通过 DMA 方式,把这个网络包放到收包队列中;然后通过硬中断,告诉中断处理程序已经收到了网络包。

网卡中断处理程序会为网络帧分配内核数据结sk_buff,并将其拷贝到 sk_buff缓冲区中;然后再通过软中断,通知内核收到了新的网络帧。

接下来,内核协议栈从缓冲区中取出网络帧,并通过网络协议栈,从下到上逐层处理这个网络帧

  • 在链路层检查报文的合法性,找出上层协议的类型(比如 IPv4 还是 IPv6),再去掉帧头、帧尾,然后交给网络层。
  • 网络层取出 IP 头,判断网络包下一步的走向,比如是交给上层处理还是转发。当网络层确认这个包是要发送到本机后,就会取出上层协议的类型(比如 TCP 还是 UDP),去掉 IP 头,再交给传输层处理。
  • 传输层取出 TCP 头或者 UDP 头后,根据 源 IP、源端口、目的 IP、目的端口 四元组作为标识,找出对应的 Socket,并把数据拷贝到 Socket 的接收缓存中。
image.png
网络包的发送

应用程序调用 Socket API(比如 send)发送网络包。由于这是一个系统调用,所以会陷入到内核态的套接字层中。套接字层会把数据包放到 Socket 发送缓冲区中。

网络协议栈从 Socket 发送缓冲区中,取出数据包;再按照 TCP/IP 栈,从上到下逐层处理。比如,传输层和网络层,分别为其增加 TCP 头和 IP 头,执行路由查找确认下一跳的 IP,并按照 MTU 大小进行分片。

分片后的网络包,再送到网络接口层,进行物理地址寻址,以找到下一跳的 MAC 地址。然后添加帧头和帧尾,放到发包队列中。这一切完成后,会有软中断通知驱动程序:发包队列中有新的网络帧需要发送。

最后,驱动程序通过 DMA ,从发包队列中读出网络帧,并通过物理网卡把它发送出去。

处理线程

TODO

网络监控工具全景图

网络监控工具.png

性能指标

带宽

表示链路的最大传输速率,单位是b/s(比特 / 秒)。

吞吐量

表示单位时间内成功传输的数据量,单位通常为 b/s(比特 / 秒)或者 B/s(字节 / 秒)。吞吐量受带宽限制

延时

表示从网络请求发出后,一直收到远端响应,所需要的时间延迟。在不同场景中,这一指标可能会有不同含义。比如,它可以表示,建立连接需要的时间(比如 TCP 握手延时),或一个数据包往返所需的时间(比如 RTT)。

PPS

Packet Per Second(包 / 秒) 的缩写,表示以网络包为单位的传输速率。PPS通常用来评估网络的转发能力。


网络基准测试

转发性能测试PPS

Linux 内核自带的高性能网络测试工具 pktgen。pktgen 支持丰富的自定义选项,方便你根据实际需要构造所需网络包,从而更准确地测试出目标服务器的性能。
不过,在 Linux 系统中,你并不能直接找到 pktgen 命令,因为 pktgen 作为一个内核线程来运行,需要你加载 pktgen 内核模块后,再通过 /proc 文件系统来交互。

# modprobe pktgen
# ls /proc/net/pktgen/
  kpktgend_0  kpktgend_1  pgctrl

根据上面的结果,我们发现,PPS 为 12 万,吞吐量为 61 Mb/s,没有发生错误。那么,12 万的 PPS 好不好呢?

作为对比,你可以计算一下千兆交换机的 PPS。交换机可以达到线速(满负载时,无差错转发),它的 PPS 就是 1000Mbit 除以以太网帧的大小,即 1000Mbps / ((64+20)*8bit) = 1.5 Mpps(其中,20B 为以太网帧前导和帧间距的大小)。

即使是千兆交换机的 PPS,也可以达到 150 万 PPS,比我们测试得到的 12 万大多了。所以,看到这个数值你并不用担心,现在的多核服务器和万兆网卡已经很普遍了,稍做优化就可以达到数百万的 PPS。
而且,如果你用了DPDK 或 XDP ,还能达到千万数量级。

TDP/UDP 性能

iperfnetperf 都是最常用的网络性能测试工具,用来测试TCP 和 UDP的吞吐量。它们都以客户端和服务器通信的方式,测试一段时间内的平均吞吐量。这里以iperf 命令为例。

  • 常用命令

  • 实践
    在目标机器上启动iperf 服务端

    # iperf3 -s -i 1 -p 10000
    -s 表示启动服务端
    -i 表示汇报间隔
    -p 表示监听端口
    

    在另一台机器上运行客户端

    # iperf3 -c 192.168.0.30 -b 1G -t 15 -P 2 -p 10000
    -c 表示启动客户端
    -b 表示目标带宽
    -t 表示测试时间
    -P 表示并发数
    -p 表示目标服务器的监听端口
    
    无标题.png

从上面可以看出目标机器的吞吐量为866 Mb/s。

HTTP

测试HTTP的性能,也有大量工具可以使用,比如 ab,webbench等。这里以 ab 为例

  • 安装

    • ubuntu
      apt-get install -y apache2-utils
      
    • centos
      yum install -y httpd-tools
      
  • 常用命令

  • 实践

    • 在目标机器上,使用 Docker 启动一个 Nginx 服务,然后用 ab 来测试它的性能。
      docker run -p 80:80 -itd nginx
      
    • 在另一台机器上,运行ab命令,测试nginx性能
      # ab -c 1000 -n 10000 http://192.168.0.30/ # -c 表示并发量100,10000表示总的
      
应用负载性能

TODO


网络配置

root@VM-0-12-ubuntu:~# ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 172.17.0.12  netmask 255.255.240.0  broadcast 172.17.15.255
        inet6 fe80::5054:ff:fed7:21c8  prefixlen 64  scopeid 0x20<link>
        ether 52:54:00:d7:21:c8  txqueuelen 1000  (Ethernet)
        RX packets 160252  bytes 164031108 (164.0 MB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 64627  bytes 10431076 (10.4 MB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
  • 网络接口的状态标志
    输出的 RUNNING,都表示物理网络是连通的,即网卡已经连接到了交换机或者路由器中。

  • MTU的大小
    规定了最大的 IP 包大小,。MTU 默认大小是 1500。

  • 网络接口的IP地址,子网,以及MAC地址

  • 网络收发的字节数,包数,错误数以及丢包的情况

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

查看网卡带宽

# ethtool eth0 | grep Speed

连通性和延时查看:ping hping3 telnet nc 命令

ping 命令

确定网络主机的连通状态

  • 发指定个数ping包
    • linux
      ping -c 4 www.baidu.com 
      
    • windows
  • 指定ping报文数据包大小
    ping -s 512 www.baidu.com
    
hping3 命令

出于安全的考虑,很多网络服务会把ICMP禁止掉,这也就导致我们无法用 ping ,hping3是一个测试网络包处理能力的性能工具,也可以用来测试延时

# hping3 -c 3 -S -p 80 baidu.com  # -c 表示3次 -S 表示Tcp SYN -p 表示端口
HPING baidu.com (eth0 39.156.69.79): S set, 40 headers + 0 data bytes
len=40 ip=39.156.69.79 ttl=249 id=6995 sport=80 flags=SA seq=0 win=8192 rtt=29.8 ms
len=40 ip=39.156.69.79 ttl=249 id=32254 sport=80 flags=SA seq=1 win=8192 rtt=36.0 ms
len=40 ip=39.156.69.79 ttl=249 id=20666 sport=80 flags=SA seq=2 win=8192 rtt=32.0 ms
telnet 命令

用于确定目标主机端口是否打开

# telnet www.baicu.com 80
nc 命令
  • 连接服务器某端口
    可用来测试对方端口是否打开
    nc -v 127.0.0.1 12345
    

套接字信息:netstat 命令

netstat
netstat -[atunlp]

-a:列出目前系统上所有的连接,监听,socket
-t:列出tcp网络数据包数据
-u:列出udp网络数据包数据
-n:不列出进程的服务名称,以端口号来显示
-l:列出目前正在监听的网络
-p:列出网络服务的PID
  • 查看某个端口是否被占用
netstat -anp | grep 80
  • 统计TCP套接字各状态信息
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print (a,S[a])}'
  • netstat 中Recv-Q 和 Send-Q的意义
    • 当套接字处于连接状态时

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


      image.png
      • Recv-Q 表示全连接队列的长度。
      • Send-Q 表示全连接队列的最大长度。

      全连接,是指服务器收到了客户端的 ACK,完成了 TCP 三次握手,然后就会把这个连接挪到全连接队列中。这些全连接中的套接字,还需要被 accept 系统调用取走。

      与全连接队列相对应的,还有一个半连接队列。半连接是指还没有完成 TCP 三次握手的连接,连接只进行了一半。服务器收到了客户端的 SYN 包后,就会把这个连接放到半连接队列中,然后再向客户端发送 SYN+ACK 包。


网络吞吐和 PPS:sar 命令

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

# sar -n DEV 1
Linux 4.15.0-118-generic (VM-0-12-ubuntu)   12/28/2020  _x86_64_    (1 CPU)

11:25:06 AM  IFACE   rxpck/s  txpck/s   rxkB/s   txkB/s  rxcmp/s  txcmp/s  rxmcst/s  %ifutil
11:25:07 AM   eth0   8.00      6.00     0.64     0.97    0.00     0.00     0.00      0.00
11:25:07 AM     lo   0.00      0.00     0.00     0.00    0.00     0.00     0.00      0.00

11:25:07 AM  IFACE   rxpck/s  txpck/s   rxkB/s   txkB/s  rxcmp/s  txcmp/s  rxmcst/s  %ifutil
11:25:08 AM  eth0    3.96      3.96     0.32     0.80    0.00      0.00     0.00      0.00
11:25:08 AM  lo      7.92      7.92     0.64     0.64    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。

统计socket连接信息
sar -n SOCK 1 1
image.png
  • totsck 当前被使用的socket总数
  • tcpsck 当前正在被使用的TCP的socket总数
  • udpsck 当前正在被使用的UDP的socket总数
  • rawsck 当前正在被使用于RAW的skcket总数
  • if-frag 当前的IP分片的数目
  • tcp-tw TCP套接字中处于TIME-WAIT状态的连接数量

iftop 命令

iftop是类似于top的实时流量监控工具。

中间的<= =>这两个左右箭头,表示的是流量的方向。

TX:发送流量
RX:接收流量
TOTAL:总流量
Cumm:运行iftop到目前时间的总流量
peak:流量峰值
rates:分别表示过去 2s 10s 40s 的平均流量

常用命令
  • -i设定监测的网卡

    iftop -i eth1
    
  • -B 以bytes为单位显示流量(默认是bits)

    iftop -B
    
  • -n使host信息默认直接都显示IP

    iftop -n
    
  • -N使端口信息默认直接都显示端口号

    iftop -N
    
  • -P使host信息及端口信息默认就都显示

  • -F显示特定网段的进出流量,如# iftop -F 10.10.1.0/24或# iftop -F 10.10.1.0/255.255.255.0

  • -h(display this message),帮助,显示参数信息

进入iftop画面后的一些操作命令
  • 按h切换是否显示帮助;

  • 按n切换显示本机的IP或主机名;

  • 按s切换是否显示本机的host信息;

  • 按d切换是否显示远端目标主机的host信息;

  • 按t切换显示格式为2行/1行/只显示发送流量/只显示接收流量;

  • 按N切换显示端口号或端口服务名称;

  • 按S切换是否显示本机的端口信息;

  • 按D切换是否显示远端目标主机的端口信息;

  • 按p切换是否显示端口信息;

  • 按P切换暂停/继续显示;

  • 按b切换是否显示平均流量图形条;

  • 按B切换计算2秒或10秒或40秒内的平均流量;

  • 按T切换是否显示每个连接的总流量;

  • 按l打开屏幕过滤功能,输入要过滤的字符,比如ip,按回车后,屏幕就只显示这个IP相关的流量信息;

  • 按L切换显示画面上边的刻度;刻度不同,流量图形条会有变化;

  • 按j或按k可以向上或向下滚动屏幕显示的连接记录;

  • 按1或2或3可以根据右侧显示的三列流量数据进行排序;

  • 按<根据左边的本机名或IP排序;

  • 按>根据远端目标主机的主机名或IP排序;

  • 按o切换是否固定只显示当前的连接;

  • 按f可以编辑过滤代码,这是翻译过来的说法,我还没用过这个!

  • 按!可以使用shell命令,这个没用过!没搞明白啥命令在这好用呢!

  • 按q退出监控。


延展阅读

  • 文件描述符的数量
  • syn 洪泛攻击
  • 大量请求带来的中断处理中断不均
  • dropped 上升
  • 连接状态的跟踪(CONNTRACK)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容