33.6. 调优 UDP 连接
在开始调优 Red Hat Enterprise Linux 以改进 UDP 流量的吞吐量之前,有一个现实的预期很重要。UDP 是一个简单协议。与 TCP 相比,UDP 不包含如,流控制、拥塞控制和数据可靠性等功能。这样很难在吞吐量率接近网络接口控制器(NIC)的最大速度的 UDP 上达到可靠的通信。
33.6.1. 检测数据包丢弃 复制链接链接已复制到粘贴板!
在内核可以丢弃数据包的网络堆栈中有多个级别。Red Hat Enterprise Linux 提供了不同的工具来显示这些级别的统计信息。使用它们来识别潜在的问题。
请注意,您可以忽略非常小的数据包丢弃率。但是,如果您遇到非常大的丢失率,请考虑调优措施。
如果网络堆栈无法处理传入的流量,则内核会丢弃网络数据包。
流程
识别由于套接字缓冲太小,或者应用程序处理速度较慢导致的特定于 UDP 协议的数据包丢弃:
nstat -az UdpSndbufErrors UdpRcvbufErrors
# nstat -az UdpSndbufErrors UdpRcvbufErrors #kernel UdpSndbufErrors 4 0.0 UdpRcvbufErrors 45716659 0.0
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 输出中的第二列列出了计数。
33.6.2. 使用 iperf3 测试 UDP 吞吐量 复制链接链接已复制到粘贴板!
iperf3
工具提供了一个服务器和客户端模式,来在两个主机之间执行网络吞吐量测试。
应用程序的吞吐量取决于许多因素,如应用程序使用的缓冲区大小。因此,使用测试工具(如 iperf3
)测量的结果可能与生产工作负载下服务器上应用程序的测量结果有很大不同。
先决条件
-
iperf3
软件包安装在客户端和服务器上。 - 两个主机上没有其他服务导致严重影响测试结果的网络流量。
- 可选:增加服务器和客户端上最大 UDP 套接字大小。详情请参阅 增加系统范围的 UDP 套接字缓冲区。
流程
可选:在服务器和客户端上显示网络接口控制器(NIC)的最大网络速度:
ethtool enp1s0 | grep "Speed"
# ethtool enp1s0 | grep "Speed" Speed: 10000Mb/s
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在服务器中:
显示最大 UDP 套接字读缓冲区大小,并记录值:
sysctl net.core.rmem_max
# sysctl net.core.rmem_max net.core.rmem_max = 16777216
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示的值以字节为单位。
在
firewalld
服务中临时打开默认的iperf3
端口 5201 :firewall-cmd --add-port=5201/tcp --add-port=5201/udp
# firewall-cmd --add-port=5201/tcp --add-port=5201/udp
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 请注意,
iperf3
只打开服务器上的一个 TCP 套接字。如果客户端希望使用 UDP,则首先连接到此 TCP 端口,然后服务器在同一端口号上打开一个 UDP 套接字,以执行 UDP 流量吞吐量测试。因此,您必须在本地防火墙中为 TCP 和 UDP 协议打开端口 5201。在服务器模式下启动
iperf3
:iperf3 --server
# iperf3 --server
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 服务现在等待传入的客户端连接。
在客户端中:
显示客户端用于连接服务器的接口的最大传输单元(MTU),并记录值:
ip link show enp1s0
# ip link show enp1s0 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 ...
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示最大 UDP 套接字写缓冲区大小,并记录值:
sysctl net.core.wmem_max
# sysctl net.core.wmem_max net.core.wmem_max = 16777216
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 显示的值以字节为单位。
开始测量吞吐量:
iperf3 --udp --time 60 --window 16777216 --length 1472 --bitrate 2G --client 192.0.2.1
# iperf3 --udp --time 60 --window 16777216 --length 1472 --bitrate 2G --client 192.0.2.1
Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
--udp
:使用 UDP 协议进行测试。 -
--time <seconds>
:定义客户端停止传输时的时间(以秒为单位)。 -
--window <size>
:设置 UDP 套接字缓冲区大小。理想情况下,客户端和服务器上的大小相同。如果不同,则将此参数设置为:比客户端上的net.core.wmem_max
或服务器上的net.core.rmem_max
更小的值。 -
--length <size>
:设置要读和写的缓冲区的长度。将这个选项设置为最大的未碎片的有效负载。按如下所示计算理想的值:MTU - IP 标头(IPv4 为 20 字节,IPv6 为 40 字节) - 8 字节 UDP 标头。 --bitrate <rate>
:将比特率限制为指定的值,单位是比特每秒。您可以指定单位,如2G
代表 2 Gbps。将此参数设置为您希望正常工作的值,并在稍后的测量中增加它。如果客户端发送数据包的速度比传输路径上的设备快,或者比服务器可以处理的速度快,则数据包可能会被丢弃。
-
--client <server>
:启用客户端模式并设置运行iperf3
服务器的服务器的 IP 地址或名称。
-
等待
iperf3
完成测试。服务器和客户端都显示每秒的统计信息,并在结尾显示总结。例如,以下是在客户端上显示的总结:[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams [ 5] 0.00-60.00 sec 14.0 GBytes 2.00 Gbits/sec 0.000 ms 0/10190216 (0%) sender [ 5] 0.00-60.04 sec 14.0 GBytes 2.00 Gbits/sec 0.002 ms 0/10190216 (0%) receiver
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams [ 5] 0.00-60.00 sec 14.0 GBytes 2.00 Gbits/sec 0.000 ms 0/10190216 (0%) sender [ 5] 0.00-60.04 sec 14.0 GBytes 2.00 Gbits/sec 0.002 ms 0/10190216 (0%) receiver
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 在这个示例中,平均比特率为 2 Gbps,没有丢失数据包。
在服务器中:
-
按 Ctrl+C 停止
iperf3
服务器。 关闭
firewalld
中的端口 5201 :firewall-cmd --remove-port=5201/tcp --remove-port=5201/udp
# firewall-cmd --remove-port=5201/tcp --remove-port=5201/udp
Copy to Clipboard Copied! Toggle word wrap Toggle overflow
-
按 Ctrl+C 停止
33.6.3. MTU 大小对 UDP 流量吞吐量的影响 复制链接链接已复制到粘贴板!
如果您的应用程序使用大型 UDP 消息大小,则使用巨型帧可以提高吞吐量。根据 IEEE 802.3 标准,没有 Virtual Local Area Network (VLAN)标签的默认以太网帧最大大小为 1518 字节。这些帧的每一个都包含一个 18 字节标头,为有效负载保留 1500 字节。因此,对于服务器通过网络传输的每 1500 字节数据,有 18 字节(1.2%)是开销。
巨型帧是非标准帧,其比 1500 字节的标准以太网有效负载有更大的最大传输单位(MTU)。例如,如果您使用最大允许 9000 字节有效负载的 MTU 配置巨型帧,则每个帧的开销减少到 0.2%。
传输路径上的所有网络设备和涉及的广播域都必须支持巨型帧,并使用相同的 MTU。由于传输路径上的 MTU 设置不一致,所以数据包碎片和重组会减少网络吞吐量。
不同的连接类型有一些 MTU 限制:
- Ethernet :MTU 限制为 9000 字节。
- datagram 模式中的 IP over InfiniBand (IPoIB):MTU 限制为比 InfiniBand MTU 少 4 字节。
- 内存网络通常支持更大的 MTU。详情请查看相应的文档。
33.6.4. CPU 速度对 UDP 流量吞吐量的影响 复制链接链接已复制到粘贴板!
在批量传输中,UDP 协议比 TCP 效率要低得多,主要是因为 UDP 中缺少数据包聚合。默认情况下,不会启用 Generic Receive Offload (GRO)和 UDP Fragmentation Offload (UFO)功能。因此,对于高速链路上的批量传输,CPU 频率可能会限制 UDP 吞吐量。
例如,在具有高最大传输单元(MTU)和大型套接字缓冲区的调优的主机上,3 GHz CPU 可以处理全速发送或接收 UDP 流量的 10 GBit NIC 的流量。但是,当您传输 UDP 流量时,您可以预计在 3 GHz 下,每 100 MHz CPU 速度会损失大约 1-2 Gbps 速度。另外,如果 3 GHz 的 CPU 速度可以达到接近 10 Gbps,则在 40 GBit NIC 上,相同的 CPU 将 UDP 流量限制为大约 20-25 Gbps。
33.6.5. 增加系统范围的 UDP 套接字缓冲区 复制链接链接已复制到粘贴板!
套接字缓冲区临时存储内核已收到或应发送的数据:
- 读套接字缓冲区保存内核已收到但应用程序尚未读取的数据包。
- 写套接字缓冲区保存应用程序已写到缓冲区,但内核尚未将它们传给 IP 堆栈和网络驱动程序的数据包。
如果 UDP 数据包太大,且超过速度缓冲区大小或数据包以太快速度发送或接收,则内核会丢弃任何新传入的 UDP 数据包,直到数据从缓冲区删除为止。在这种情况下,增加套接字缓冲区可以防止数据包丢失。
设置太大的缓冲区大小浪费内存。每个套接字可以设置为应用程序所请求的大小,内核会加倍这个值。例如,如果应用程序请求 256 KiB 套接字缓冲区大小,并打开 100 万个套接字,则对于潜在的套接字缓冲区空间,系统只需要 512 GB RAM (512 KiB x 100万)。
先决条件
- 您遇到了明显的 UDP 数据包丢弃率。
流程
根据您的要求,创建
/etc/sysctl.d/10-udp-socket-buffers.conf
文件,并设置最大读或写缓冲区大小,或两个都设置:net.core.rmem_max = 16777216 net.core.wmem_max = 16777216
net.core.rmem_max = 16777216 net.core.wmem_max = 16777216
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 指定值(以字节为单位)。本例中的值将缓冲区的最大大小设置为 16 MiB。这两个参数的默认值都为
212992
字节(208 KiB)。从
/etc/sysctl.d/10-udp-socket-buffers.conf
文件中载入设置:sysctl -p /etc/sysctl.d/10-udp-socket-buffers.conf
# sysctl -p /etc/sysctl.d/10-udp-socket-buffers.conf
Copy to Clipboard Copied! Toggle word wrap Toggle overflow 将应用程序配置为使用更大的套接字缓冲大小。
net.core.rmem_max
和net.core.wmem_max
参数定义应用程序中setsockopt()
函数可以请求的最大缓冲区大小。请注意,如果您将应用程序配置为不使用setsockopt()
函数,则内核将使用rmem_default
和wmem_default
参数的值。详情请查看应用程序的编程语言的文档。如果您不是应用程序的开发人员,请联系开发人员。
- 重启应用程序以使用新的 UDP 缓冲区大小。
验证
使用您在遇到数据包丢弃时使用的相同方法来监控数据包丢弃统计信息。
如果数据包仍然以较低的速率发生,请进一步增加缓冲区大小。