在服务器之间,windows-in-Finland <-> linux-in-Germany
我发现上传速度比下载速度慢 100 倍(windows -> linux
比 慢 100 倍windows <- linux
)。
详细信息和现有研究
我最初在世界各地的 Windows 客户端上观察到了这个问题,并注意到我也可以在受控数据中心环境中重现它。
为了重现该问题,我使用了数据中心提供商 Hetzner,机器Windows
位于芬兰(专用服务器,Windows Server 2019),上传到以下两个位置:
- Linux Hetzner 专用德国:速度慢
- Linux Hetzner Cloud VM 德国:快速
两者都位于同一个数据中心园区,因此都37 ms
ping
从 Windows 机器获取了数据。虽然芬兰和德国之间的连接通常位于 Hetzner 的专用网络上,但由于C-LION1 2024 波罗的海海底电缆中断(Hetzner 对此的状态消息),它目前正通过公共互联网路由重新路由,因此该连接使用正常的公共互联网路由和对等连接进行“模拟”。
我正在用 来测量iperf3
:windows <- linux
C:\Users\Administrator\Downloads\iperf3.17.1_64\iperf3.17.1_64>iperf3.exe -c linux-germany-dedicated.examle.com
Connecting to host linux-germany-dedicated.examle.com, port 5201
[ 5] local 192.0.2.1 port 62234 connected to 192.0.2.2 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 15.8 MBytes 132 Mbits/sec
[ 5] 1.00-2.00 sec 1.88 MBytes 15.7 Mbits/sec
[ 5] 2.00-3.00 sec 1.38 MBytes 11.5 Mbits/sec
[ 5] 3.00-4.00 sec 1.75 MBytes 14.7 Mbits/sec
[ 5] 4.00-5.00 sec 2.25 MBytes 18.9 Mbits/sec
[ 5] 5.00-6.00 sec 2.88 MBytes 24.1 Mbits/sec
[ 5] 6.00-7.00 sec 3.25 MBytes 27.3 Mbits/sec
[ 5] 7.00-8.00 sec 3.38 MBytes 28.3 Mbits/sec
[ 5] 8.00-9.00 sec 2.75 MBytes 23.1 Mbits/sec
[ 5] 9.00-10.00 sec 1.25 MBytes 10.5 Mbits/sec
更多iperf3
观察:
- 另一个方向(添加
-R
到iperf3
)要快得多,约为 900 Mbit/s。(请注意,Linux 端正在使用 BBR 拥塞控制,这可能有助于该方向。) iperf3
当使用30个连接(带有)下载时-P 30
,1 Gbit/s 连接已达到最大限额,这表明问题出在单个TCP 上传连接的上传吞吐量上。- 在芬兰,将 Windows 计算机替换为 Linux 计算机时,两个方向的连接速度都达到了 1 Gbit/s 的最大值。这让我得出结论,Windows 的介入是错误的。
- 请注意,有一篇Microsoft 文章声称这
iperf3
是 Windows 上高性能测量的最佳方法。这与这个问题无关,因为它仅适用于 >= ~10 Gbit/s 的连接,而 iperf3 在同一数据中心的多台 Windows/Linux 机器上运行这一事实证明,iperf3
在两个方向上都可以轻松实现 1 Gbit/s 的速度。
2021 年,Dropbox 发布了一篇文章《提升 Dropbox 上传速度并改进 Windows 的 TCP 堆栈》,指出 Windows 对 TCP 重传的处理不正确(不完整);微软同时发布了《算法改进提升了互联网上的 TCP 性能》。
这似乎很大程度上解释了它,并且Wireguard 速度慢但仅适用于 Windows 上传显示了一个潜在的解决方案,即将 RSS(接收方缩放)队列的数量更改为 1:
ethtool -L eth0 combined 1
这从 (我的专用 Linux 服务器上的 16 个线程) 更改16
为 1,并将聚合的 iperf3 上传速度从10.5
增加到330
Mbit/s。
这很好,但应该是 1000 Mbit/s。
特别奇怪的是:windows -> linux-Hetzner-Cloud
通过测试windows -> Hetzner-dedicated
,我观察到了完美的上传速度:
C:\Users\Administrator\Downloads\iperf3.17.1_64\iperf3.17.1_64>iperf3.exe -c linux-germany-hcloud.example.com
Connecting to host linux-germany-hcloud.example.com, port 5201
[ 5] local 192.0.2.1 port 55615 connected to 192.0.2.3 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 108 MBytes 903 Mbits/sec
[ 5] 1.00-2.00 sec 112 MBytes 942 Mbits/sec
...
[ 5] 9.00-10.00 sec 112 MBytes 942 Mbits/sec
这很奇怪,因为云机器的规格要低得多。它有 8 个虚拟核心,但它的ethtool -l
输出已经默认为,Combined: 1
因为作为虚拟机,它根本不支持 RSS:
root@linux-germany-hcloud ~ # ethtool -x enp1s0
RX flow hash indirection table for enp1s0 with 1 RX ring(s):
Operation not supported
RSS hash key:
Operation not supported
RSS hash function:
toeplitz: on
xor: off
crc32: off
因此,性能较弱的机器似乎没有出现问题。也许专用机器中存在一些巧妙的 NIC 硬件问题,从而导致出现问题?可能是什么原因?
我已经尝试禁用 TCP 分段卸载 ( ethtool -K eth0 tso off
),但这不会影响结果。Dropbox 文章 ( flow-director-atr
) 中导致问题的功能在我的 NIC 上不可用,所以不可能是它。
问题
如何解释两台 Linux 服务器之间上传速度进一步增加 3 倍的瓶颈?
我怎样才能从 Windows 实现快速上传?
更多环境信息
- 两台 Linux 机器使用相同的 Linux 版本
6.6.33 x86_64
和相同的sysctl
s(通过 NixOS 确保),它们是:net.core.default_qdisc=fq net.core.rmem_max=1073741824 net.core.wmem_max=1073741824 net.ipv4.conf.all.forwarding=0 net.ipv4.conf.net0.proxy_arp=0 net.ipv4.ping_group_range=0 2147483647 net.ipv4.tcp_congestion_control=bbr net.ipv4.tcp_rmem=4096 87380 1073741824 net.ipv4.tcp_wmem=4096 87380 1073741824
- Windows 服务器 2019
Version 1809 (OS Build 17763.6293)
编辑1
我发现从 Windows 到其他 Hetzner 专用机器的上传速度为 950 Mbit/s。上传速度慢的专用机器都有一个共同点,那就是它们都配有 Intel 10 Gbit/s 网卡;来自lspci
:
01:00.0 Ethernet controller: Intel Corporation 82599ES 10-Gigabit SFI/SFP+ Network Connection (rev 01)
lsmod | grep ixgbe
ixgbe
建议在此处使用
该驱动程序。 上面的Dropbox 文章ixgbe
中也提到了这一点。他们链接的论文“为什么 Flow Director 会导致数据包重新排序?”特别提到了这一点。 我还发现了这个 e1000-devel 线程,其中有人在 2011 年提到了这个问题,但没有提出解决方案。Intel 82599
当使用同一型号服务器中的 1-GbitIntel Corporation I210 Gigabit Network Connection (rev 03)
卡时,问题消失,我得到了 950 Mbit/s。
因此,似乎有一些特定的因素82599ES
导致ixgbe
了该问题。
编辑 2:英特尔Flow Director
和尝试树外ixgbe
谷歌搜索intel disable flowdirector
显示https://access.redhat.com/solutions/528603提到了英特尔 82599。
帮助:
Intel Flow Director 是英特尔 NIC 和驱动程序的一项功能,可将类似的网络流量(即“流”)智能且可编程地引导到特定的接收队列中。
默认情况下,Flow Director 以 ATR(应用程序目标接收)模式运行。当收到之前未见过的流量时,它会执行常规 RSS 样式的哈希处理。但是,当传输流量时,该流量的元组(或“流”)将输入到接收哈希表中。在同一元组上接收的未来流量将在传输它的核心上接收。然后可以将发送和接收过程固定到与接收队列相同的核心,以实现最佳的 CPU 缓存亲和性。
请注意,社区研究表明,当进程在 CPU 之间迁移时,ATR 可能会导致 TCP 无序流量。使用 ATR 模式时,最好将进程明确固定到 CPU。
Dropbox 文章中提到了 FlowDirector,也是如此ATR
。
所提到的“社区研究”与 Dropbox 所引用的论文“Flow Director 为什么会导致数据包重新排序?”是同一篇。
按照建议做
ethtool -K net0 ntuple on
将速度从 20 Mbit/s 提高到 130 Mbit/s(使用默认的ethtool -L net0 combined 16
)。运行时间更长(iperf3 --time 30
)会使它在 16 秒后降至 80 Mbit/s。ntuple on
与一起使用combined 16
不会进一步提高速度。
所以这不是一个完整的解决方案。
接下来测试该options ixgbe FdirMode=0
方法。
在ram256g-1
:
rmmod ixgbe; modprobe ixgbe FdirMode=0; sleep 2; ifconfig net0 94.130.221.7/26 ; ip route add 192.0.2.2 dev net0 proto static scope link ; ip route add default via 192.0.2.2 dev net0 proto static ; echo done
dmesg
节目
ixgbe: unknown parameter 'FdirMode' ignored
尽管https://www.kernel.org/doc/Documentation/networking/ixgbe.txt记录了这一点:
FdirMode
--------
Valid Range: 0-2 (0=off, 1=ATR, 2=Perfect filter mode)
Default Value: 1
Flow Director filtering modes.
因此0=off
看起来比其他两个更受欢迎,据称这就是ntuple
on/off
两者之间的切换。
https://access.redhat.com/solutions/330503说
英特尔选择在其 SourceForge 驱动程序中将某些配置作为模块参数公开,但是上游 Linux 内核的策略是,当可以以现有方式进行配置时,不会将功能作为模块选项公开,因此您只会在上游 Linux 内核树之外的英特尔驱动程序上看到一些模块参数。
Red Hat 遵循上游内核方法,因此这些选项不会出现在 RHEL 版本的驱动程序中,但通常可以通过
ethtool
(或无需重新加载模块)完成相同的操作。
这表明这0=off
实际上是无法实现的。
或者也许它可以与modprobe.d
选项一起使用但不能与modprobe
命令一起使用?
相关代码:
- 带有以下选项的旧内核
FdirMode
: - 新内核不包含:
- https://github.com/torvalds/linux/blob/b86545e02e8c22fb89218f29d381fa8e8b91d815/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c#L648
- 建议仅当 RSS 队列长度为
> 1
- 因此,将队列长度设置为 1
ethtool -L
(即--set-channels
)可能已经可以实现它。
- 建议仅当 RSS 队列长度为
- https://github.com/torvalds/linux/blob/b86545e02e8c22fb89218f29d381fa8e8b91d815/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c#L648
但似乎https://github.com/intel/ethernet-linux-ixgbe仍在积极开发中,并支持所有旧选项。还支持FdirPballoc
从未存在过的内容torvalds/linux
。描述如下:https: //forum.proxmox.com/threads/pve-kernel-4-10-17-1-wrong-ixgbe-driver.35868/#post-175787
也相关: https: //www.phoronix.com/news/Intel-IGB-IXGBE-Firmware-Update
也许我应该尝试构建并加载它?
从该驱动程序中,FDirMode
还删除了:
- https://github.com/intel/ethernet-linux-ixgbe/commit/a9a37a529704c584838169b4cc1f877a38442d36
- https://github.com/intel/ethernet-linux-ixgbe/commit/a72af2b2247c8f6bb599d30e1763ff88a1a0a57a
来自https://lists.osuosl.org/pipermail/intel-wired-lan/Week-of-Mon-20160919/006629.html:
ethtool -K ethX ntuple on
这将启用“完美过滤”模式,但目前还没有过滤器,因此接收到的数据包将回退到 RSS。
尝试过
ethtool -K net0 ntuple on
ethtool --config-ntuple net0 flow-type tcp4 src-ip 192.0.2.1 action 1
沒有提高速度。
我还发现 Linux 上的速度6.3.1
似乎是 90 Mbit/s,而在 上是 25 Mbit/s 6.11.3
。
在ethernet-linux-ixgbe
Hetzner 救援系统上编译树外版本(目前还没有针对 Linux 的版本):Linux (old)
6.3.1
6.11
wget https://github.com/intel/ethernet-linux-ixgbe/releases/download/v5.21.5/ixgbe-5.21.5.tar.gz
tar xaf *.tar.gz
cd ixgbe-*/src && make -j
# because disconnecting the ethernet below will hang all commands
# from the Rescue Mode's NFS mount if not already loaded into RAM
ethtool --help
timeout 1 iperf3 -s
dmesg | grep -i fdir
modinfo /root/ixgbe-*/src/ixgbe.ko # shows all desired options
rmmod ixgbe; insmod /root/ixgbe-*/src/ixgbe.ko; sleep 2; ifconfig eth1 94.130.221.7/26 ; ip route add 192.0.2.2 dev eth1 scope link ; ip route add default via 192.0.2.2 dev eth1 ; echo done
iperf3 -s
该驱动程序开箱即用,提供更稳定的 450 Mbit/s。
rmmod ixgbe; insmod /root/ixgbe-*/src/ixgbe.ko FdirPballoc=3; sleep 2; ifconfig eth1 94.130.221.7/26 ; ip route add 192.0.2.2 dev eth1 scope link ; ip route add default via 192.0.2.2 dev eth1 ; echo done
dmesg | grep -i fdir
iperf3 -s
沒有帶來任何改善。
也可以尝试:
AtrSampleRate
值为 0 表示应禁用 ATR 并且不会进行任何采样。
rmmod ixgbe; insmod /root/ixgbe-*/src/ixgbe.ko AtrSampleRate=0; sleep 2; ifconfig eth1 94.130.221.7/26 ; ip route add 192.0.2.2 dev eth1 scope link ; ip route add default via 192.0.2.2 dev eth1 ; echo done
dmesg | grep -i atrsample
iperf3 -s
沒有帶來任何改善。
ethtool -L net0 combined 1
也没有带来任何改善,并且
ethtool -K eth1 ntuple on
ethtool -L eth1 combined 12 # needed, otherwise the out-of-tree ixgbe driver complains with `rmgr: Cannot insert RX class rule: Invalid argument` when `combined 1` is set
ethtool --config-ntuple eth1 flow-type tcp4 src-ip 192.0.2.1 action 1
也没有带来任何改善。
编辑 3:更改 NIC
我把Linux服务器的网卡从Intel 82599ES换成了Intel X710,使用Linuxi40e
驱动。
问题依然存在。
我怀疑这是因为 X710 也支持 Intel Flow Director。
部分缓解ethtool -L eth0 combined 1
与 82599ES 具有同样的效果。
命令
ethtool --set-priv-flags eth0 flow-director-atr off
(这对于来说是可能的i40e
但不是ixgbe
)Dropbox提到,因为解决方法只实现了相同的加速ethtool -L eth0 combined 1
(大约400 Mbit / s)。
有趣的是,Hetzner 报告称,Hetzner Cloud 机器也采用 Intel X710,但它们没有出现该问题。
我似乎找到了获得全速的解决方案(以下有警告):
这
SACK
Linux 内核的 TCP 支持我之前尝试过第一行(效果一般),但使用第二行禁用 SACK 完全解决了这个问题,使 Windows 机器实现了千兆位的上传速度。
每条线路单独使用并不能带来改进,但结合起来可以解决问题。
这解决了我们的 Intel X710 和 Intel 82599ES 服务器的问题。
警告:
我认为禁用 SACK 的一个副作用是,如果出现数据包丢失,连接速度会暂时下降,比启用 SACK 时下降得更快。但是,它确实会在几秒钟内恢复,平均而言,我观察到使用这些设置从 Windows Server 2019 成功实现全千兆速度上传。我很快会在 Windows-10-over-the-Internet 情况下对其进行更多测试,因为到目前为止,我只测试了 Windows-Server-2019-HEL1 -> Linux-FSN1。
编辑:我现在已经确认这
sysctl -w net.ipv4.tcp_sack=0
对存在数据包丢失的长距离 WAN 连接是有害的。一旦发生数据包丢失,连接速度就会大幅下降。因此,仅建议在您知道数据包丢失率较低的连接上采用全速方法和两种设置。如果您从一般互联网接收数据,最好只使用
并保留
sysctl -w net.ipv4.tcp_sack=1
。这样在互联网上会更加可靠。由于Dropbox 文章(以及引用的微软声明)也提到了 SACK,因此禁用 SACK 会产生一定影响,这是有道理的。
我还不明白是什么原因导致我的
观察。
net.ipv4.tcp_sack
在虚拟机主机上进行设置应该没有效果,因为 Linux客户机应该控制 TCP,而不是主机;客户机确实有tcp_sack=1
默认值,但它仍然有效。也许还有更多 NIC 设置可以达到与在内核中禁用 SACK 相同的效果,我还没有发现,或者专用服务器网络路径上的设备无法很好地处理 SACK,而这些设备在 Hetzner Cloud 机器的网络路径上不存在。这篇文章提到了网络设备给 SACK 带来的问题,但它提到的大多是连接的完全停滞而不是速度减慢:
何时关闭 TCP SACK?
我还发现 Windows 11(我测试了 23H2)已修复此问题。根据问题中的 Microsoft 文章,Windows Server 2022 也已修复此问题。