在Linux中阻塞TCP连接

奇怪的问题。 我在达拉斯有服务器“ALPHA”,在香港有服务器“BETA”,互相间隔约195ms。 ALPHA以1Gbps的速率连接,10Mbps的BETA连接。 偶尔当他们通过TCP相互通信时,连接挂起。 最终,ALPHA放弃并closures连接,但BETA仍然认为连接已build立,并等待很长时间直到最终超时。

例。

在BETA上, wget -O /dev/null ALPHA:50001/1mb.test

 --2013-05-19 02:45:54-- http://ALPHA:50001/1mb.test Resolving dfw... ip.address.redacted Connecting to ALPHA|ip.address.redacted|:50001... connected. HTTP request sent, awaiting response... 200 OK Length: 1000000 (977K) [application/octet-stream] Saving to: `/dev/null' 

并在收到的0字节处冻结。 请注意,它确实从服务器获得了200 OK,所以他们似乎握手成功。 为了消除wget作为问题的一部分,我做了一个telnet:

 telnet ALPHA 50001 Trying ip.address.redacted... Connected to ALPHA. Escape character is '^]'. GET /1mb.test HTTP/1.0 HTTP/1.1 200 OK Server: nginx Date: Sun, 19 May 2013 22:43:48 GMT Content-Type: application/octet-stream Content-Length: 1000000 Last-Modified: Sat, 21 Jan 2012 21:47:29 GMT Connection: close ETag: "4f1b3271-f4240" Accept-Ranges: bytes 

它也冻结在这一点上。

两台服务器都有iptables规则-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

这是在上面的wget冻结过程中在ALPHA上运行的tcpdump。 http://pastebin.com/axX7ap6T

这个问题只是偶尔发生。 有时它工作得很好。 实际上,如果我跑3-5次左右,通常一切都开始在第四次或第五次尝试。

testing版可以与GAMMA,DELTA和我的其他服务器通信没有问题。 只有在与ALPHA交谈时才会发生。 ICMP ping显示没有丢包,但即使有丢包,也会减慢速度,不会断开连接。 这两台机器都具有相同的CentOS 6.4 64位操作系统,内核2.6.32-358.6.2.el6.x86_64。 没有有用的login/ var / log文件。 ALPHA正在使用nginx-1.4.1-1.el6.ngx.x86_64在50001上进行监听。 nginx访问日志文件显示冻结连接期间传递的200(请求正常)43440个字节。

这个问题似乎不是nginx相关的,因为我有一个ssh连接也冻结在同一天通信中。 其他服务器连接到该nginx,从来没有任何问题。

总之,这似乎是在这个特定的沟通中发生的事情:

 BETA -> ALPHA "SYN!" ALPHA -> BETA "SYN Acknowledgement" BETA -> ALPHA "ACK" ALPHA -> BETA "Established" BETA -> ALPHA "GET /file HTTP/1.0" ALPHA -> BETA "200 OK, here's a bunch of data" BETA freezes, gets no data. 

任何人看到这样的情况?

也许一个MTU / MSS问题? 小的初始数据包通过,大的(数据传输)在某个地方被杀死了?

解决方法是将MTU(双方)从1500减less到TCPMSS例如,或者对受影响的连接使用Netfilter目标TCPMSS (或对不同的连接进行不同的处理)。

但真正的解决scheme是让pathMTU发现再次工作。 因此,检查是否阻塞了ICMP数据包(所需的碎片:types3,代码4)。 使用tcpdump -i $ifname -n icmp来查看这些数据包是否到达。

确实发生碎片整理。 这就是IPTABLES检查数据包的做法。 它必须重新组装它们才能validation内容。

就我而言,当我在CentOS 7系统上进行网页浏览的时候,我会看到定期的ping dropouts和web浏览器,或者我的PuttY会话从窗口中永远不会被神秘地挂起。

我使用了Mick提供的方法来确定MTU大小。 这种方法的问题是,如果你设置的MTU尺寸很小,你会得到一个错误的碎片阅读。 所以设置的大小(巨型帧/ 9000),然后开始ping探针。

在将MTU设置为1472(我确定的是正确的值)之后,浏览时的ping问题就消失了。 希望当我从Windows下ssh,这也将工作。

我的第一个猜测是,这是一个TCP窗口缩放问题:

https://en.wikipedia.org/wiki/TCP_window_scale_option#Possible_side_effects

禁用它的两端,看看问题是否消失。 另一个选项(如豪克build议)是发生碎片整理。

您可以使用ping来检查数据包的分段,一个简单的HOWTO在这里:

http://muzso.hu/2009/05/17/how-to-determine-the-proper-mtu-size-with-icmp-pings

编辑:错过了一个字。