吞吐量测试和故障排除

流量概况

首先,您需要了解流量概况。您需要收集以下信息

  • 连接的源/目标是什么?
    • 裸机还是虚拟机?
    • 操作系统
    • IP 地址
    • MAC 地址
    • CPU 信息
    • RAM
  • 连接的完整流量路径是什么?
    • 第 1 层连接
    • 第 2 层跃点
    • 第 3 层跃点
  • 连接正在使用什么服务、协议和端口?
    • TCP/UDP
    • 非标准端口
    • 常用吞吐量测试 - HTTP、FTP、高端口 TCP
  • 客户端和服务器之间有多少个已建立的并发连接?
  • 平均数据包大小是多少?
  • TCP 特定问题
    • 窗口大小是多少?
    • 是否存在任何数据包重新排序?
    • 是否存在数据包丢失以及恢复机制是什么?
    • 您是否正在使用 SACK 或普通 ACK?
  • 有多少其他流量正在通过 Cumulus Linux 交换机?
    • 端口的速度是多少?

使用开源工具进行网络测试

测试网络性能需要以各种速率生成流量,并测量吞吐量、丢包、延迟、抖动等。本文介绍了多种免费提供的开源网络测试工具。但是,运行软件只是故事的一半。调整主机以高效生成和接收网络流量以及监控硬件负载也同样重要。本文探讨的所有工具都具有不同的功能、统计报告和操作。

以高于 1Gbps 的数据速率生成流量需要强大的服务器硬件。在不深入探讨计算机体系结构的情况下,CPU、内存、PCI 总线和网络接口控制器 (NIC) 都在生成和接收网络数据中发挥作用。通常,瓶颈是执行客户端或服务器进程的 CPU 内核。PCI 总线也可能限制性能,具体取决于 PCI 版本。最后,NIC 必须能够支持其尝试发送的流量。

许多示例和调整信息来自 Energy Sciences Network。它们更详细地介绍了主机调整和不同工具的各种功能。

iPerf3

这是原始 iPerf 工具的完整重写版本。它具有许多相同的功能,尽管它尚不支持多播。以下是一些基本命令以开始使用,这些命令与版本 2 中可用的选项相同。对于带宽测试,iPerf3 优于 iPerf1 或 2。

NVIDIA 测试了 iPerf3,并在 Debian Wheezy 7.9 上发现了一些功能问题,而 NVIDIA 在 Debian Jessie 8.3 上未发现任何问题。iPerf 版本 1 和 2 在 Debian Wheezy 上工作。Nvidia 不提供对第三方工具的安装或使用的支持。此处提供的信息仅供参考。

服务器命令

在 IPv4 的默认端口上启动服务器(默认)

iperf3 -s 

在守护程序模式下启动服务器

iperf3 -s -D

在端口 5003 上启动服务器

iperf3 -s -p 5003

开始使用 0.5 秒的时间间隔

iperf3 -s -i 0.5

客户端命令

运行 30 秒的测试,每 1 秒给出结果

iperf3 -c <dst-ip> -i 1 -t 30 

使用细粒度间隔报告计数器可以帮助在检查特定吞吐量测试速度缓慢的原因时提供更多信息。

从 remotehost 到 localhost 运行测试

iperf3 -c <dst-ip> -i 1 -t 20 -R 

运行具有 4 个并行流且具有 32M TCP 缓冲区的测试

iperf3 -c <dst-ip> -w 32M -P 4 

窗口大小对于 TCP 测试非常重要。TCP 窗口决定了在收到 ACK 之前可以有多少字节和数据包处于传输中。对于直接连接的服务器和客户端,小窗口可能会导致高速,但对于客户端和服务器之间网络延迟较高的网络,小窗口可能会导致低速。随着 RTT 的增加,数据包和 ACK 之间的时间增加,这会导致更多的数据包处于传输中。如果 TCP 窗口太小而无法容纳,则发送方会减慢发送数据包的速度,然后才会耗尽窗口。当使用巨型帧时,这一点变得更加重要。

当使用负载平衡功能(例如 LACP 绑定链路、MLAG 交换机或 ECMP 路由)时,利用并行会话可以帮助提高吞吐量数字。在这些流量负载平衡功能中,通常使用源 IP 地址和目标 IP 地址以及端口对流进行哈希处理。这意味着单个流始终会被哈希到同一物理链路和路径。要测试流量路径的完全利用率,请为客户端和服务器连接使用多个 IP 地址和端口。您应该将每个并发连接的吞吐量结果加在一起,以获得基础设施的总带宽。-P 选项创建具有不同源端口的多个会话,根据流量哈希算法,这可能会产生更高的吞吐量结果。

运行 200 Mbps UDP 测试

iperf3 -c <dst-ip> -u -i 1 -b 200M

使用 UDP 进行测试时,可以使用 -b 修饰符来设置目标吞吐量速率。对于不受限制的带宽目标,请使用 -b 0。对于 UDP,如果不设置此值,吞吐量值可能会非常低。

许多客户端/服务器 NIC 卡执行 TCP 校验和/标头卸载。这意味着 NIC 本身会执行这些计算。但是对于 UDP,软件会执行标头处理。因此,UDP 和 TCP 之间的性能数字可能不一致。

优化

iPerf3 具有许多与现代服务器硬件配合良好的优化功能。它还具有新功能来改进如何测量统计信息。

在收集结果之前运行测试 2 秒,以允许 TCP 慢启动完成。-O 标志将省略模式设置为 2 秒延迟,-i 标志设置 ½ 秒报告间隔。

iperf3 -c <dst-ip> -O 2 -i 0.5

使用 -Z 标志启用零拷贝模式,该模式使用 sendfile() 系统调用。这使用更少的 CPU 将数据放在 PCI 总线上。

iperf3 -c <dst-ip> -Z

使用 -J 标志以 JSON 格式输出结果,以便大多数编码语言轻松解析。此输出在整个测试运行完成后打印。

iperf3 -c <dst-ip> -J 

为发送方 (-A 2) 或发送方、接收方 (-A 2,3) 设置 CPU 亲和性,其中核心编号从 0 开始。这与运行 numactl -C 4 iperf3 具有相同的效果。

iperf3 -c <dst-ip> -A 2,3 

使用细粒度间隔报告计数器可以帮助在检查特定吞吐量测试速度缓慢的原因时提供更多信息。

如果您使用 -P 标志,则无需使用 -A x,y-P 标志创建多个连接,服务器端似乎在所有可用核心之间平衡线程。

注意事项

如上述注释中所述,iPerf 可以根据设置给出差异很大的结果集。但是,iPerf 存在一些问题,使其难以用于现代网络上的性能测试。测试中重要的因素

  • TCP 窗口大小,使用 -w 标志控制
  • TCP 与 UDP 协议,使用 -u 修饰符控制
  • 目标吞吐量速率,使用 -b 修饰符控制
  • CPU 利用率,使用 -Z 修饰符和 -A 修饰符控制
  • 用于平均计算的数据时间集,使用 -O 修饰符控制
  • 端口上的并发连接,使用 -P 修饰符控制

默认情况下,iPerf 使用 TCP/UDP 端口 5201/5001(取决于版本)作为传输期间的端口。这对于 ECMP 测试效果不佳。指定 -P 标志告诉 iPerf 生成多个客户端线程,其中源端口使用 5201 以及一系列临时端口。但是,当使用此方法时,也很常见看到很多这些消息:bind failed: Address already in use

iPerf(版本 2)

从发行版的存储库安装 iPerf 时,很可能是版本 2。这是一个相当旧的版本,并且不再维护。

多播

iPerf2 的一个独特功能是能够发送多播流量。以下是要使用的客户端和服务器命令

iperf -c 224.0.0.1 -u -b 512k  #source
iperf -B 224.0.0.1 -su         #receiver

这会导致服务器侦听组播地址,这意味着它向连接的网络设备发送 IGMP 报告。在客户端,请务必为多播范围创建静态路由,下一跳指向被测网络设备(假设这从 eth1 输出)。

ip route add 224.0.0.0/4 dev eth1

注意事项

对于 2Gbps 以上的 UDP,结果不一致。NVIDIA 建议使用 nuttcp 或 iPerf3 进行高速 UDP 测试。但是,如果将流量速率保持在 2Gbps 以下,则可以接受用于测试网络。高于此值,统计信息完全不可靠。因此,本文将不将其作为可行的性能测试工具进行介绍。

nuttcp

该工具在过去 30 年中不断发展,并具有多个有用的功能。它支持速率限制、多个并行流和基于计时器的执行。它还包括 IPv6、IPv4 多播以及设置参数(例如 TCP MSS 或 TOS/DSCP 位)的功能。

查看应用程序的帮助文件,很容易看出此工具具有许多独特的功能。需要了解的一件事是存在客户端(发送器/接收器)和服务器实体。您可以从客户端命令控制服务器设置,例如 TCP 窗口大小。服务器进程会自动派生到后台并运行,直到发生错误情况或某些东西杀死它们。以下示例演示了一些基本知识。

服务器命令

在默认端口 (5000) 上启动服务器

nuttcp -S

在 IPv6 的默认端口上启动服务器

nuttcp -s -6

在端口 5003 上启动服务器

nuttcp -S -P 5003

发送器命令

运行 10 秒测试,每秒给出结果

nuttcp -i 1 <server>

运行更长时间的测试需要 -T 标志,您可以在其中指定持续时间,如下所示

-T30 = 30 sec, -T1m = 1 min, and -T1h = 1 hr

运行 10 秒测试,将发送器/接收器窗口以及服务器接收/发送窗口大小设置为 32KB。您还可以以兆字节 (-w5m) 或千兆字节 (-w5g) 为单位设置窗口

nuttcp -w32 -ws32 <server>

默认流量使用 TCP,但您可以将其作为 UDP 运行,数据报大小为 8192 字节(默认)

nuttcp -u <server>

运行 50Mbps 的 10 秒 UDP 测试,并报告吞吐量和数据包丢失

nuttcp -u -R50m <server>

运行 1200 字节数据报的 10 秒 UDP 测试

nuttcp -u -l1200 <server>

接收器命令

反向运行 10 秒测试(服务器 → 客户端),每 1 秒给出结果

nuttcp -r -i 1 <server>

特殊功能

UDP 突发模式

从 6.2.8 版本开始,nuttcp 包括 UDP 的突发模式,这对于查找受缓冲不足限制的网络路径很有用。为此,请设置瞬时数据速率和可选数据包突发。以 Kbps (-R100)、Mbps (-R5m)、Gbps (-R5g) 或 PPS (-R1000p) 为单位指定速率。突发只是数据包的计数。

以 300 Mbps 的瞬时速率发送 300 Mbps 的 UDP,突发 20 个数据包,持续 5 秒

nuttcp -u -Ri300m/20 -i 1 -T5 <server>

此测试可能会显示少量丢失。如果在相同的瞬时速率下增加突发大小,它也会增加网络缓冲的压力。随着传输设备溢出其缓冲区,这会逐渐显示更多丢失。

在具有 9000 字节 MTU 的 10GbE 网络上,您可以以 300 Mbps 的瞬时速率发送 8972 字节 UDP 数据报,并突发 100 个数据包。这应该是无损的

nuttcp -l8972 -T30 -u -w4m -Ri300m/100 -i1 <server>

同样,增加突发值并重新测试最终会显示网络中发生缓冲区耗尽的位置

10G UDP 测试

nuttcp 可能是高速 UDP 测试的最佳工具。使用 UDP 创建完整的 10 Gbps 流量流几乎不需要任何努力,但这需要巨型 MTU 大小的数据包 (9K)

nuttcp -l8972 -T30 -u -w4m -Ru -i1 <server>
CPU 亲和性

版本 7.1 中引入的较新功能之一是 CPU 亲和性。这允许用户指定在哪个核心上执行进程。

发送多个流时,您可以使用 CPU 亲和性绑定来确保两个进程不会最终在同一 CPU 核心上。请务必在预期目标端口上启动服务器。此外,使用统计信息输出标识符有助于使用 s1s2 标记结果

nuttcp -i1 -xc 2/2 -Is1 -u -Ru -l8972 -w4m -p 5500 <server> & \
nuttcp -i1 -xc 3/3 -Is2 -u -Ru -l8972 -w4m -p 5501 <server>

带宽控制器 (bwctl)

此工具是 iPerf2、iPerf3 和 nuttcp 的包装器。此包装器的文档可在此处获取:here

使用 bwctl 的优势在于它是一个集中式带宽测试工具,它利用上面列出的所有工具来提供带宽测试结果。您可以阅读此处的安装指南。

Ostinato

Ostinato 是一个用于生成数据包的开源工具。它主要通过 GUI 操作,但可以轻松安装在 Linux 桌面环境中。

虽然没有 CLI,但它确实有一个 Python API,您可以使用它来生成数据包。

Cumulus Linux 交换机输出

在执行带宽测试时,将测试工具的结果与 Cumulus Linux 交换机上的各种输出进行交叉引用非常有价值。

交换机上的流量服务

吞吐量级别可能会根据您应用于流量的服务而变化。理想情况下,所有流量都应通过交换机 ASIC 进行硬件交换。但是,应用于流量的某些服务需要将流量从 ASIC 转移到交换机 CPU。由于交换机 CPU 在处理和转发数据包方面速度较慢,因此吞吐量可能会受到这些功能的影响。一些可能导致软件处理数据包的功能包括

  • 封装方法
  • GRE
  • NAT
  • PBR

查看应用于流量的常规功能也很重要

  • 第 2 层与第 3 层交换
  • 用于流量的 Netfilter ACL

故障排除输出

您应该检查这两个输出以验证吞吐量

  • cl-netstat
  • ethtool -S swpX

cl-netstat

此命令是 Linux 中提供的接口计数器的包装器。ip -s link show up 的输出打印所有 TX 和 RX 数据包的计数器。但是,这些本机 Linux 命令无法清除计数器。cl-netstat 命令添加了此功能,并且可以在受控环境下跟踪各个连接。以下示例显示了通过 Cumulus Linux 交换机在客户端和服务器之间运行的 iPerf3 测试的结果

客户端 iPerf3 结果
root@CLIENT:~# iperf3 -c 10.1.1.100
Connecting to host 10.1.1.100, port 5201
[  4] local 10.1.2.100 port 53984 connected to 10.1.1.100 port 5201
[ ID] Interval           Transfer     Bandwidth       Retr  Cwnd
[  4]   0.00-1.00   sec   980 MBytes  8.22 Gbits/sec    0   5.17 MBytes       
...   
[  4]   9.00-10.00  sec   951 MBytes  7.98 Gbits/sec    0   5.17 MBytes       
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval           Transfer     Bandwidth       Retr
[  4]   0.00-10.00  sec  9.32 GBytes  8.01 Gbits/sec    0             sender
[  4]   0.00-10.00  sec  9.29 GBytes  7.98 Gbits/sec                  receiver
cl-netstat 结果
cumulus@switch:~$ sudo cl-netstat   
Kernel Interface table
Iface      MTU    Met    RX_OK    RX_ERR    RX_DRP    RX_OVR    TX_OK    TX_ERR    TX_DRP    TX_OVR  Flg
-------  -----  -----  -------  --------  --------  --------  -------  --------  --------  --------  -----
swp13     1500      0    62622         0         0         0  6904270         0         0         0  BMRU
swp14     1500      0  6904271         0         0         0    62623         0         0         0  BMRU

在上面的示例中,您可以看到流量已在 swp13 和 swp14 之间成功流动,而没有丢弃任何数据包。

ethtool -S

同样,您可以使用 ethtool -S 的输出来交叉引用从 cl-netstat 获得的输出。

cumulus@switch:~$ sudo ethtool -S swp13
NIC statistics:
     HwIfInOctets: 5583156718
     HwIfInUcastPkts: 5140969
     HwIfInBcastPkts: 14
     HwIfInMcastPkts: 9272
     HwIfOutOctets: 210229661164
     HwIfOutUcastPkts: 139033950
     HwIfOutMcastPkts: 17657
     HwIfOutBcastPkts: 8556
     HwIfInDiscards: 0
     HwIfInL3Drops: 0
     HwIfInBufferDrops: 0
     HwIfInAclDrops: 63
     HwIfInDot3LengthErrors: 0
     HwIfInErrors: 0
     SoftInErrors: 0
     SoftInDrops: 0
     SoftInFrameErrors: 0
     HwIfOutDiscards: 0
     HwIfOutErrors: 0
     HwIfOutQDrops: 0
     HwIfOutNonQDrops: 0

cumulus@switch:~$ sudo ethtool -S swp14
NIC statistics:
     HwIfInOctets: 210229250162
     HwIfInUcastPkts: 139051524 
     HwIfInBcastPkts: 5 
     HwIfInMcastPkts: 9230 
     HwIfOutOctets: 5583641007 
     HwIfOutUcastPkts: 5124014 
     HwIfOutMcastPkts: 17875 
     HwIfOutBcastPkts: 8711 
     HwIfInDiscards: 0 
     HwIfInL3Drops: 0 
     HwIfInBufferDrops: 0 
     HwIfInAclDrops: 54 
     HwIfInDot3LengthErrors: 0 
     HwIfInErrors: 0 
     SoftInErrors: 0 
     SoftInDrops: 0 
     SoftInFrameErrors: 0
     HwIfOutDiscards: 0
     HwIfOutErrors: 0
     HwIfOutQDrops: 0
     HwIfOutNonQDrops: 0 

ethtool 中的计数器比 cl-netstat 的输出大得多,因为您无法清除 ethtool 计数器。要检查的关键输出是验证接收或发送中的错误是否正在增加。

计数器的方向性也很重要。通过 HwIfIn 前缀的入口丢包表示接收流量速率太快。这通常表示突发流量或沿流量路径的阻塞点。通过 HwIfOut 前缀的出口丢包表示多对一问题,其中多个 RX 接口正尝试将流量发送到单个 TX 接口。这并不总是一个坏结果,因为它表示接口的完全带宽利用率。

RX 错误

如果在带宽测试期间 RX_ERR 下的计数器正在增加,则交换机的数据包转发可能存在问题。以下是一些先前编写的解决此场景的文章