搜索

31.5. 为高吞吐量调整 TCP 连接

download PDF

在 Red Hat Enterprise Linux 上调整与 TCP 相关的设置,以提高吞吐量、减少延迟或防止问题(如数据包丢失)。

31.5.1. 使用 iperf3 测试 TCP 吞吐量

iperf3 工具提供了一个服务器和客户端模式,来在两个主机之间执行网络吞吐量测试。

注意

应用程序的吞吐量取决于许多因素,如应用程序使用的缓冲大小。因此,使用测试工具(如 iperf3)测量的结果可能与生产工作负载下服务器上应用程序的测量结果有很大不同。

先决条件

  • iperf3 软件包安装在客户端和服务器上。
  • 两个主机上没有其他服务导致严重影响测试结果的网络流量。
  • 对于 40 Gbps 和更快的连接,网卡支持 Accelerated Receive Flow Steering (ARFS),且该功能在接口上被启用。

流程

  1. 可选:在服务器和客户端上显示网络接口控制器(NIC)的最大网络速度:

    # ethtool enp1s0 | grep "Speed"
       Speed: 100000Mb/s
  2. 在服务器中:

    1. firewalld 服务中临时打开默认的 iperf3 TCP 端口 5201 :

      # firewall-cmd --add-port=5201/tcp
      # firewall-cmd --reload
    2. 在服务器模式下启动 iperf3

      # iperf3 --server

      服务现在正在等待传入的客户端连接。

  3. 在客户端中:

    1. 开始测量吞吐量:

      # iperf3 --time 60 --zerocopy --client 192.0.2.1
      • --time <seconds>:定义客户端停止传输时的时间(以秒为单位)。

        将此参数设置为您希望正常工作的值,并在稍后的测量中增加它。如果服务器以比传输路径上的设备更快的速度发送数据包,或者客户端可以处理,则可以丢弃数据包。

      • --zerocopy :启用零复制方法,而不使用 write() 系统调用。只有在您想模拟具有零复制的应用程序或在单一流上达到 40 Gbps 和更高时,才需要这个选项。
      • --client <server> :启用客户端模式并设置运行 iperf3 服务器的服务器的 IP 地址或名称。
  4. 等待 iperf3 完成测试。服务器和客户端都显示每秒的统计信息,并在结尾显示总结。例如,以下是在客户端上显示的总结:

    [ ID] Interval         Transfer    Bitrate         Retr
    [  5] 0.00-60.00  sec  101 GBytes   14.4 Gbits/sec   0   sender
    [  5] 0.00-60.04  sec  101 GBytes   14.4 Gbits/sec       receiver

    在这个示例中,平均比特率为 14.4 Gbps。

  5. 在服务器中:

    1. Ctrl+C 停止 iperf3 服务器。
    2. 关闭 firewalld 中的 TCP 端口 5201:

      # firewall-cmd --remove-port=5201/tcp
      # firewall-cmd --reload

其他资源

  • iperf3 (1) 手册页

31.5.2. 系统范围的 TCP 套接字缓冲区设置

套接字缓冲区临时存储内核已收到或应发送的数据:

  • 读套接字缓冲区保存内核已收到但应用程序尚未读取的数据包。
  • 写套接字缓冲区保存应用程序已写到缓冲区,但内核尚未将它们传给 IP 堆栈和网络驱动程序的数据包。

如果 TCP 数据包太大,且超过缓冲区大小或数据包以很快的速度发送或接收,则内核会丢弃任何新传入的 TCP 数据包,直到数据从缓冲区中删除为止。在这种情况下,增加套接字缓冲区可以防止数据包丢失。

net.ipv4.tcp_rmem(读)和 net.ipv4.tcp_wmem(写)套接字缓冲区内核设置包含三个值:

net.ipv4.tcp_rmem = 4096  131072  6291456
net.ipv4.tcp_wmem = 4096  16384   4194304

显示的值以字节为单位,Red Hat Enterprise Linux 通过以下方式使用它们:

  • 第一个值是最小缓冲区大小。新套接字不能有更小的尺寸。
  • 第二个值是默认的缓冲区大小。如果应用程序没有设置缓冲区大小,则这是默认值。
  • 第三个值是自动调优缓冲区的最大大小。在应用程序中使用带有 SO_SNDBUF 套接字选项的setsockopt()函数禁用这个最大缓冲区大小。

请注意,net.ipv4.tcp_rmemnet.ipv4.tcp_wmem 参数为 IPv4 和 IPv6 协议设置套接字大小。

31.5.3. 增加系统范围的 TCP 套接字缓冲区

系统范围的 TCP 套接字缓冲区临时存储内核已收到或应发送的数据。net.ipv4.tcp_rmem(读)和 net.ipv4.tcp_wmem(写)套接字缓冲区内核设置各包含三个设置:最小值、默认值和最大值。

重要

设置太大的缓冲区大小浪费内存。每个套接字可以设置为应用程序所请求的大小,内核会加倍这个值。例如,如果应用程序请求 256 KiB 套接字缓冲区大小,并打开 100 万个套接字,则系统只能将最多 512 GB RAM (512 KiB x 100万)用于潜在的套接字缓冲空间。

另外,最大缓冲区大小的值太大可能会增加延迟。

先决条件

  • 您遇到 TCP 数据包丢弃率很高。

流程

  1. 确定连接的延迟。例如,从客户端 ping 服务器以测量平均 Round Trip Time (RTT):

    # ping -c 10 server.example.com
    ...
    --- server.example.com ping statistics ---
    10 packets transmitted, 10 received, 0% packet loss, time 9014ms
    rtt min/avg/max/mdev = 117.208/117.056/119.333/0.616 ms

    在本例中,延迟为 117 ms。

  2. 使用以下公式为您要调整的流量计算 Bandwidth Delay 产品(BDP):

    connection speed in bytes * latency in ms = BDP in bytes

    例如,要计算有 117 ms 延迟的 10 Gbps 连接的 BDP:

    (10 * 1000 * 1000 * 1000 / 8) * 117 = 10683760 bytes
  3. 根据您的要求,创建 /etc/sysctl.d/10-tcp-socket-buffers.conf 文件,并设置最大取或写缓冲区大小:

    net.ipv4.tcp_rmem = 4096 262144 21367520
    net.ipv4.tcp_wmem = 4096 24576 21367520

    指定值(以字节为单位)。当您尝试识别您环境的优化值时,请使用以下经验法则:

    • 默认缓冲区大小(第二个值):仅稍微增加这个值或将其最多设为 524288 (512 KiB)。太高的默认缓冲区大小可能会导致缓冲区崩溃,从而导致延迟激增。
    • 最大缓冲区大小(第三个值):通常 BDP 的两倍到三倍的值就足够了。
  4. /etc/sysctl.d/10-tcp-socket-buffers.conf 文件中载入设置:

    # sysctl -p /etc/sysctl.d/10-tcp-socket-buffers.conf
  5. 将应用程序配置为使用更大的套接字缓冲区大小。net.ipv4.tcp_rmemnet.ipv4.tcp_wmem 参数中的第三个值定义应用程序中 setsockopt () 函数可以请求的最大缓冲区大小。

    详情请查看应用程序的编程语言的文档。如果您不是应用程序的开发人员,请联系开发人员。

  6. 如果您更改了 net.ipv4.tcp_rmemnet.ipv4.tcp_wmem 参数中的第二个值,请重新启动应用程序以使用新的 TCP 缓冲区大小。

    如果您只更改了第三个值,则不需要重启应用程序,因为自动调整会动态应用这些设置。

验证

  1. 可选:使用 iperf3 测试 TCP 吞吐量
  2. 使用您遇到数据包丢弃时使用的同样方法来监控数据包丢弃统计信息。

    如果数据包仍然以较低的速率发生,请进一步增加缓冲区大小。

其他资源

31.5.4. TCP 窗口扩展

在 Red Hat Enterprise Linux 中默认启用的 TCP 窗口扩展功能是 TCP 协议的扩展,可显著提高吞吐量。

例如,在具有 1.5 毫秒 Round Trip Time (RTT)的 1 Gbps 连接上:

  • 启用 TCP 窗口扩展后,大约 630 Mbps 是可行的。
  • 禁用 TCP 窗口扩展后,吞吐量下降到 380 Mbps。

TCP 提供的一个功能是流控制。通过流控制,发送方可以发送接收方所能接收的数据,但不能发送更多数据。为达到此目的,接收方公布一个 window 值,这是发送方可以发送的数据量。

TCP 最初支持最多 64 KiB 的窗口大小,但在高带宽延迟产品(BDP)下,这个值变为一种限制,因为发送方无法一次发送超过 64 KiB 的数据。高速连接可以在给定时间内传输超过 64 KiB 的数据。例如:系统间一个有 1 毫秒延迟的 10 Gbps 链接在给定时间内可传输 1 MiB 的数据。如果主机只发送 64 KiB ,然后暂停,直到其他主机接收 64 KiB,则效率很低。

要删除这个瓶颈,TCP 窗口扩展允许 TCP 窗口值算术左移,以将窗口大小增加到 64 KiB 以上。例如,最大窗口值为 65535 将 7 个位置向左移动 7 位,从而产生大约 8 MiB 的窗口大小。这可在给定时间内传输更多数据。

TCP 窗口扩展会在三向 TCP 握手中进行协商,该握手会打开每个 TCP 连接。发件方和接收方必须支持 TCP 窗口扩展功能才能正常工作。如果两个参与者没有在握手中发布窗口扩展功能,则连接将恢复为使用最初的 16 位 TCP 窗口大小。

TCP 窗口扩展默认在 Red Hat Enterprise Linux 中启用:

# sysctl net.ipv4.tcp_window_scaling
net.ipv4.tcp_window_scaling = 1

如果服务器上禁用了 TCP 窗口扩展(0),用与您设置它的相同方式恢复设置。

31.5.5. TCP SACK 如何降低数据包丢弃率

在 Red Hat Enterprise Linux (RHEL)中默认启用的 TCP Selective Acknowledgment(TCP SACK)功能是 TCP 协议的一种改进,提高了 TCP 连接的效率。

在 TCP 传输中,接收方为其接收的每个数据包将一个 ACK 数据包给发送方。例如,客户端向服务器发送了 TCP 数据包 1-10,但数据包号 5 和 6 丢失。如果没有 TCP SACK,服务器会丢弃数据包 7-10,客户端必须从丢失点重新传输所有数据包,而这效率较低。如果两个主机上都启用了 TCP SACK,客户端只需重新传输丢失的数据包 5 和 6。

重要

禁用 TCP SACK 会降低性能,并给 TCP 连接中的接收方造成较高的数据包丢弃率。

TCP SACK 默认在 RHEL 中启用。要验证:

# sysctl net.ipv4.tcp_sack
1

如果您的服务器上禁用了 TCP SACK (0),用与您设置它的同样的方式恢复设置。

Red Hat logoGithubRedditYoutubeTwitter

学习

尝试、购买和销售

社区

关于红帽文档

通过我们的产品和服务,以及可以信赖的内容,帮助红帽用户创新并实现他们的目标。

让开源更具包容性

红帽致力于替换我们的代码、文档和 Web 属性中存在问题的语言。欲了解更多详情,请参阅红帽博客.

關於紅帽

我们提供强化的解决方案,使企业能够更轻松地跨平台和环境(从核心数据中心到网络边缘)工作。

© 2024 Red Hat, Inc.