31.6. 调优 UDP 连接
在开始调优 Red Hat Enterprise Linux 以改进 UDP 流量的吞吐量之前,有一个现实的预期很重要。UDP 是一个简单协议。与 TCP 相比,UDP 不包含如,流控制、拥塞控制和数据可靠性等功能。这样很难在吞吐量率接近网络接口控制器(NIC)的最大速度的 UDP 上达到可靠的通信。
31.6.1. 检测数据包丢弃
在内核可以丢弃数据包的网络堆栈中有多个级别。Red Hat Enterprise Linux 提供了不同的工具来显示这些级别的统计信息。使用它们来识别潜在的问题。
请注意,您可以忽略非常小的数据包丢弃率。但是,如果您遇到非常大的丢失率,请考虑调优措施。
如果网络堆栈无法处理传入的流量,则内核会丢弃网络数据包。
流程
确定网络接口控制器(NIC)是否丢弃了数据包:
显示 NIC 和特定于驱动程序的统计信息:
# ethtool -S enp1s0 NIC statistics: ... rx_queue_0_drops: 17657 ...
统计的命名以及其是否可用取决于 NIC 和驱动程序。
显示接口统计信息:
# ip -s link show enp1s0 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 link/ether 52:54:00:74:79:56 brd ff:ff:ff:ff:ff:ff RX: bytes packets errors dropped missed mcast_ 84697611107 56866482 0 10904 0 0 TX: bytes packets errors dropped carrier collsns_ 5540028184 3722234 0 0 0 0
RX
代表接收的数据包和传输的数据包TX
的统计信息。
识别由于套接字缓冲太小,或者应用程序处理速度较慢导致的特定于 UDP 协议的数据包丢弃:
# nstat -az UdpSndbufErrors UdpRcvbufErrors #kernel UdpSndbufErrors 4 0.0 UdpRcvbufErrors 45716659 0.0
输出中的第二列列出了计数。
其他资源
- RHEL 网络接口丢弃数据包(红帽知识库)
- 我是否应该关注 0.05% 的数据包丢弃率?(红帽知识库)
31.6.2. 使用 iperf3 测试 UDP 吞吐量
iperf3
工具提供了一个服务器和客户端模式,来在两个主机之间执行网络吞吐量测试。
应用程序的吞吐量取决于许多因素,如应用程序使用的缓冲区大小。因此,使用测试工具(如 iperf3
)测量的结果可能与生产工作负载下服务器上应用程序的测量结果有很大不同。
先决条件
-
iperf3
软件包安装在客户端和服务器上。 - 两个主机上没有其他服务导致严重影响测试结果的网络流量。
- 可选:增加服务器和客户端上最大 UDP 套接字大小。详情请参阅 增加系统范围的 UDP 套接字缓冲区。
流程
可选:在服务器和客户端上显示网络接口控制器(NIC)的最大网络速度:
# ethtool enp1s0 | grep "Speed" Speed: 10000Mb/s
在服务器中:
显示最大 UDP 套接字读缓冲区大小,并记录值:
# sysctl net.core.rmem_max net.core.rmem_max = 16777216
显示的值以字节为单位。
在
firewalld
服务中临时打开默认的iperf3
端口 5201 :# firewall-cmd --add-port=5201/tcp --add-port=5201/udp # firewall-cmd --reload
请注意,
iperf3
只打开服务器上的一个 TCP 套接字。如果客户端希望使用 UDP,它首先连接到此 TCP 端口,然后服务器在同一端口号上打开一个 UDP 套接字,以执行 UDP 流量吞吐量测试。因此,您必须在本地防火墙中为 TCP 和 UDP 协议打开端口 5201。在服务器模式下启动
iperf3
:# iperf3 --server
服务现在等待传入的客户端连接。
在客户端中:
显示客户端用于连接服务器的接口的最大传输单元(MTU),并记录值:
# ip link show enp1s0 2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP mode DEFAULT group default qlen 1000 ...
显示最大 UDP 套接字写缓冲区大小,并记录值:
# sysctl net.core.wmem_max net.core.wmem_max = 16777216
显示的值以字节为单位。
开始测量吞吐量:
# iperf3 --udp --time 60 --window 16777216 --length 1472 --bitrate 2G --client 192.0.2.1
-
--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
在这个示例中,平均比特率为 2 Gbps,没有丢失数据包。
在服务器中:
-
按 Ctrl+C 停止
iperf3
服务器。 关闭
firewalld
中的端口 5201 :# firewall-cmd --remove-port=5201/tcp --remove-port=5201/udp # firewall-cmd --reload
-
按 Ctrl+C 停止
其他资源
-
您系统上的
iperf3 (1)
手册页
31.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。详情请查看相应的文档。
31.6.4. CPU 速度对 UDP 流量吞吐量的影响
在批量传输中,UDP 协议比 TCP 效率要低得多,主要是因为 UDP 中缺少数据包聚合。默认情况下,不会启用 Generic Receive Offload (GRO)和 Transmit Segmentation Offload (TSO)功能。因此,对于高速链路上的批量传输,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。
31.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
指定值(以字节为单位)。本例中的值将缓冲区的最大大小设置为 16 MiB。这两个参数的默认值都为
212992
字节(208 KiB)。从
/etc/sysctl.d/10-udp-socket-buffers.conf
文件中载入设置:# sysctl -p /etc/sysctl.d/10-udp-socket-buffers.conf
将应用程序配置为使用更大的套接字缓冲大小。
net.core.rmem_max
和net.core.wmem_max
参数定义应用程序中setsockopt()
函数可以请求的最大缓冲区大小。请注意,如果您将应用程序配置为不使用setsockopt()
函数,则内核将使用rmem_default
和wmem_default
参数的值。详情请查看应用程序的编程语言的文档。如果您不是应用程序的开发人员,请联系开发人员。
- 重启应用程序以使用新的 UDP 缓冲区大小。
验证
使用您在遇到数据包丢弃时使用的相同方法来监控数据包丢弃统计信息。
如果数据包仍然以较低的速率发生,请进一步增加缓冲区大小。
其他资源
- 更改套接字缓冲区大小的影响是什么?(红帽知识库)
-
您系统上的
udp(7)
和socket (7)
手册页