34.6. 调优 UDP 连接
在开始调优 Red Hat Enterprise Linux 以改进 UDP 流量的吞吐量前,有一个现实的期望很重要。UDP 是一个简单协议。与 TCP 相比,UDP 不包含这些功能,如流控制、阻塞控制和数据可靠性。这样很难与接近网络接口控制器(NIC)的最大速度的吞吐量率通过 UDP 达到可靠的通信。
34.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% 数据包丢弃率?解决方案
34.6.2. 使用 iperf3 测试 UDP 吞吐量
iperf3
工具提供了服务器和客户端模式,来在两个主机之间执行网络吞吐量测试。
应用程序的吞吐量取决于许多因素,如应用程序使用的缓冲区大小。因此,使用测试工具(如 iperf
3)测量的结果可能与生产工作负载下服务器上应用程序测量的结果有很大不同。
先决条件
-
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 标头(20 字节用于 IPv4 ,40 字节用于 IPv6) - 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)
手册页
34.6.3. MTU 大小对 UDP 流量吞吐量的影响
如果您的应用程序使用大型 UDP 消息大小,则使用巨型帧可以提高吞吐量。根据 IEEE 802.3 标准,没有 Virtual Local Area Network (VLAN)标签的默认以太网帧有1518 字节的最大大小。这些帧的每一个都包含一个 18 字节标头,给有效负载保留 1500 字节。因此,对于服务器通过网络传输的每 1500 字节数据,18 字节(1.2%)是开销。
巨型帧是非标准化的帧,其最大传输单位(MTU)比 1500 字节的标准以太网有效负载大小大。例如,如果您使用最大允许的 9000 字节有效负载配置巨型帧,则每个帧的开销减少到 0.2%。
传输路径上的所有网络设备和所涉及的广播域都必须支持巨型帧,并使用相同的 MTU。由于传输路径上的 MTU 设置不一致,数据包碎片和组装减少了网络吞吐量。
不同的连接类型有一些 MTU 限制:
- 以太网 :MTU 限制为 9000 字节。
- 数据报模式下的 IP over InfiniBand (IPoIB):MTU 限制为比 InfiniBand MTU 少 4 个字节。
- 内存网络通常支持大型 MTU。详情请查看相应的文档。
34.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,则相同的 CPU 将 40 GBit NIC 上的 UDP 流量限制在大约 20-25 Gbps。
34.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)
手册页