我有两个 Linux VM,它们之间由 50 mbps WAN 连接隔开。此 WAN 链路的 RTT 约为 70ms,因此存在一定延迟。我一直在测试每个 VM 的上传到 Internet 的吞吐量。基本设置是站点 A 具有 Internet 连接,并且还具有到站点 B 的 WAN 连接。站点 B 使用站点 A 的 Internet 连接。
我注意到站点 B 的互联网上传速度比站点 A 要慢得多。我只是使用一些互联网速度测试站点来测试我的上传速度。我使用每个站点的相同互联网速度测试站点和服务器进行测试。我也进行了很多次测试。
我运行了一些 Wireshark 测试,以查看发生了什么。我假设互联网服务器没有打开足够宽的 TCP 窗口来解释来自站点 B 的 70ms 额外延迟。然而,TCP 窗口是完全打开的,实际上是我的站点 B 服务器停止传输,等待 ACK 到来后再发送更多数据。
我查看了很多内容:TCP 时间戳、SACK 和窗口缩放均已启用。我已按如下方式增加了缓冲区:
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.ipv4.tcp_rmem = 4096 87380 33554432
net.ipv4.tcp_wmem = 4096 65536 33554432
net.core.netdev_max_backlog = 30000
net.ipv4.tcp_congestion_control=cubic
我还增加了传输队列的长度,如下所示:
ifconfig eth0 txqueuelen 10000
最后,我禁用了 VM 上的软件 TCP 段卸载(我的服务器上没有硬件 TOE)。
尽管如此,Wireshark 还是显示我获得的传输数据不超过 11,000 字节。在传输开始时我确实丢了一些数据包,但当传输真正开始时,我本以为会有更多数据传输。
有人能解释一下为什么在实际传输的数据如此之少的情况下,发送方要保留数据吗?
答案1
我在您的数据包跟踪中看到的是拥塞控制对数据包丢失做出的反应。
客户端首先发送初始 9 个段,然后是慢启动,每次收到 ACK 数据包时都会发送两个段。
慢启动算法持续进行,直到服务器发出的第一个重复 ACK 表明数据包已丢失。这种情况发生在有 20820 个字节在传输中时。此后,客户端将以较慢的速度增加拥塞窗口。
第二次拥塞发生在传输开始仅半秒后。此后,传输中的字节数从大约 15K 增长到 68012 字节,此时第三次拥塞发生,即传输开始 6 秒后。
第三次拥塞后,传输中约有 54KB 字节。该数据不断增加,直到传输中达到 94384 字节,第四次拥塞发生,此时传输已进行 10 秒。
跟踪的其余部分还出现了多起拥塞情况。如果数据包丢失的次数没有那么频繁,传输速度可能能够加快。由于它很早就出现了第一次数据包丢失,因此需要很长时间才能达到全速。
因此,您需要弄清楚为什么在 TCP 连接期间这么早就丢失了数据包。事实证明,此时丢失的数据包是连接开始时连续发送的 9 个数据包之一。这表明客户端配置的设置太高了initcwnd
。从您提供的一次数据包捕获来看,合理的设置应该是4
。
该initcwnd
设置是针对每个路由表条目单独指定的。可以使用命令查看和更改它们ip route
。