当我通过城域以太网链路传输文件时,网络上出现了过多的 TCP Dup ACK 和 TCP Fast Retransmission。两个站点通过一个 SonicWall 路由器连接,因此站点之间只有一跳距离。
这里这是 wireshark 的截图,这里是整个捕获。在此捕获中,客户端是 192.168.2.153,服务器是 192.168.1.101 以下是从我的系统到服务器的跟踪路由(ping 时间通常稳定在 10ms 以下):
user@pc567:~$ ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:e0:b8:c8:0c:7e
inet addr:192.168.2.153 Bcast:192.168.2.255 Mask:255.255.255.0
inet6 addr: fe80::2e0:b8ff:fec8:c7e/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:244994 errors:0 dropped:0 overruns:0 frame:0
TX packets:149148 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:319571991 (319.5 MB) TX bytes:12322180 (12.3 MB)
Interrupt:16
user@pc567:~$ traceroute -n 192.168.1.101
traceroute to 192.168.1.101 (192.168.1.101), 30 hops max, 60 byte packets
1 192.168.2.254 0.747 ms 0.706 ms 0.806 ms
2 192.168.1.101 8.995 ms 9.217 ms 9.477 ms
user@pc567:~$
任何有关导致此问题的原因的帮助都会很有帮助!我可以发布任何需要的详细信息。
更新:自从这个问题开始以来,我已经用 1800 cisco 路由器替换了 sonicwall。安装后数据包捕获的结果相同。由于它是城域以太网电路,因此不需要路由器。因此,我还尝试将笔记本电脑直接连接到两个站点的服务提供商设备,并将它们放在同一个子网上。这样做的数据包捕获看起来是一样的。这让我相信城域以太网电路存在问题,尽管他们继续说一切正常,测试一切正常。
答案1
我意识到这个答案被简化了,并不像我希望的那样明确,所以如果您对某个步骤有疑问,请询问!
在 Wireshark 中打开此文件后向下滚动一点,我们会看到一些不同颜色的帧。看起来很糟糕,对吧?好吧,其实没那么糟糕。稍等一下,我们会到达那里。
检查 SYN 数据包(第 37 帧)后,我们在 TCP 选项中看到 SACK 和窗口缩放。很好。SYN/ACK(第 38 帧)、SACK 和窗口缩放中也出现了同样的情况。太棒了。没有看到任何与 SACK 相关的奇怪之处。
未加载 RTT 的估计值是 SYN 数据包和第一个 ACK(第 39 帧)之间的时间。该值约为 9.3 毫秒,与您的发现相符。请注意,SYN/ACK 和 ACK(第 38 和 39 帧)之间的时间比 SYN 和 SYN/ACK(第 37 和 38 帧)之间的时间要短得多。这意味着此捕获文件是在接收方获取的,要了解为什么这并不理想,我们必须重新学习。
在发送方和接收方之间,有一段网络路径是最小的,这限制了带宽。我们刚刚从握手中获得的 RTT 估计值可以估算出这条网络路径的长度。衡量我们可以在这个管道中容纳多少个数据包的指标是管道容量或带宽延迟积- PC [bits] = R [bits/s] * RTT [s],其中 R 是最小带宽。管道容量是体积的测量单位。
想象一下花园软管。它的体积也是由长度和宽度来定义的,对吧?为了从中获取最多的水,它需要完全充满水,否则会有气隙限制水流。如果我们设法将它完全装满,它可能会溢出。我们可以使用水桶,这样就不会弄湿地板,而且如果水桶溢出也不会影响水流。
事实证明,在网络路径中情况完全相同。我们需要填充管道……换句话说,管道容量是发送方和接收方之间最小的飞行字节数(管道 + 水桶中的水量),充分利用最小带宽(不造成空气间隙)。因此,如果飞行字节数 > PC,那么我们就没问题了!
查看 TCP 跟踪 统计 -> TCP 流图 -> 时间序列图 (tcptrace)我们可以在 Y 轴上看到字节数,在 X 轴上看到时间。该曲线的导数是字节/秒,或吞吐量。请注意,黑色“线”是平坦的,这意味着吞吐量是稳定的!虽然它被蓝线打断了几次(这些是重复 ACK 中的 SACK 范围),但可以看出它不会影响吞吐量。
看到右下角的灰色实线(稍微放大一点,这就是 ACK)与黑色 TCP 段非常接近了吗?TCP 段和 ACK 之间的时间就是 RTT,这里几乎为 0!这意味着没有太多段经过此捕获点。这反过来意味着我们不能用它来估计正在传输的字节数,这就是发送方数据包捕获更好的原因。
这里的数据包在到达捕获点之前自然丢失。丢失时正在传输的每个数据段都会触发重复 ACK。因此,我们可以使用重复 ACK 的数量来估计数据包丢失时正在传输的字节数。这里我们看到大约 9、16 和 23 个段。每个段有 1448 字节的数据,因此传输的字节数在 13k 到 33k 之间。这里的吞吐量约为 3 Mbit/s(来自IO 图),并且根据我们之前测量的 RTT,我们得到的管道容量小于 3e6 [bits/s] * 10e-3 [s] / 8 字节 = 3750 字节,或者小于 3 个段。
因为这些丢失时飞行中的字节实际上并不相同(由于样本太少很难判断)我无法真正说这些是随机丢失(非常非常糟糕)还是由于队列/存储桶溢出而发生的丢失,但它们发生在飞行中的字节数 > PC 时,因此吞吐量不受影响。
您的回答似乎表明它们确实是随机的,但数量并不多以至于导致吞吐量低。
答案2
刚刚发布了我发现的内容。城域以太网提供商在某个星期六来到我们的总部。他们断开了那里的网络,并且还派了人到附近的一个分支机构。他们在两端连接了网络测试设备,很快就确定确实存在问题。几个小时后,他们就能够隔离问题。这是从提供商总部到我们总部的铜线的问题。他们说帧丢失得非常厉害,这就是导致重传的原因。他们在总部修复了铜线的问题(他们说他们必须一次拆开每根电线。在我看来这听起来很荒谬),但在他们在总部这样做之后,问题就解决了。
答案3
查看您提供的捕获(感谢您这样做!)我可以看到开头有一个非常经典的重传模式。您可以在数据包 50 附近看到它。在 51 和 52 之间有一个丢失的数据包。发生的事情是这样的:
- --> 数据包 50 数据
- <-- 数据包 51 ACK 数据包 50。
- --> 数据包 52 数据
- <-- 数据包 53 ACK 数据包 50。
- --> 数据包 54 数据
- <-- 数据包 55 ACK 数据包 50。
一个数据包被丢弃了,接收方通过继续确认数据包直到它目前看到的内容来指示这一点。这里有趣的是,双方TCP SACK Permitted Option = True
在协商连接时都进行了设置,因此数据包 55 应该有一个 SACK 标头,但实际上没有。选择性确认允许接收方指示“我已经看到了 51 之前的所有内容,还有 53-55”,这减少了恢复全速所需的重新传输次数。
由于无法使用 SACK,因此会回退到标准 TCP 重传方法,重复“我已经看到最多 50 个”直到另一端弄明白并重新传输 50 个及以后的所有内容。
数据包 66 进行了重新传输,紧接着是对数据包 56 的 ACK。第二次重新传输(数据包 72)后,连接恢复正常。
首先,SACK 标头似乎被 Sonicwall 剥离,导致重新传输无法以协商的速度恢复。我个人认为 SACK 剥离毫无意义,但其他人可能不同意。
从我在此捕获的信息来看,您偶尔会看到数据包丢失,这导致 TCP 连接需要通过正常的重新传输协议。防火墙阻碍了双方协商的重新传输方法,因为不允许使用。