我正在分析HP刀片服务器上运行的客户端和Linuxnetworking服务器之间的stream量,当Web服务器closures连接时,客户端有时会卡住等待更多数据。
Web服务器运行apache2,由于某种原因select使用connection-close运行HTTP / 1.1,而不是让客户端在同一个连接上发送多个请求,并closures连接,就像标准的HTTP / 1.1那样离开服务器数千个TIME_WAIT套接字,而不是将该状态推送给客户端)…
无论如何,有时一个HTTP请求被破坏,仍然不知道它在哪里实际上打破。 在服务器上一切看起来很好,除了客户端开始发送大量的RST数据包之间的哎呀。
我有从Web服务器和客户端通过NAT的tcpdump捕获,我会怀疑NAT,如果它不是在networking服务器上的一个非常奇怪的行为。
当Web服务器提供HTTP GET请求时,第一个传出数据包是IP有效负载中的2960字节,有线2974。 这非常奇怪,因为在客户端的NAT中,客户端接收两个1514字节的数据包,其中有1460字节的TCP有效载荷。
离开networking服务器上接口的下一个和即将到来的数据包使用MTU内的有效载荷1460(有线1514)。
我相信一些魔术是在位于networking服务器和networking之间的(思科)SLB中完成的,所以第一个2960的DF包被SLB挤压,并通过一些先进的L3拦截在SLB中神奇地分裂。
Q1)为什么apache webserver / tcp stack甚至会尝试在MTU设置为1500的接口上推送一个2960字节的数据包?
Q2)如何通过两个数据包到达客户端的networking?
Q3)即使没有设置“需要分片”的ICMP到达,Web服务器如何知道MTU应该减less到1460,因为所有的分组都已经设置了DF位。
不要问我为什么问这些问题,我只是一个大型组织中的人,试图理解为什么事情不可行。
我有一些有趣的tcpdump日志,如果需要我可以发布,我只需要replace公共IP地址和这样的…
如果你正在捕获服务器上的数据包,那么你可能会看到TCP发送比MTU更大的数据段。 然而,线路上的数据包只有MTU大小。 您可以通过在networking设备(交换机)上捕获来validation这一点。或者,在远程(客户端)机器上捕获数据包将显示每个数据包<= MTU。
这是因为启用了TSO / GSO后,TCP段被NIC硬件分割成MTU大小的数据包。 由于tcpdump在软件层捕获,因此看到比MTU更大的段被发送到NIC卡进行进一步传输。
如果禁用NIC的tso / gso,那么您将看到所有传出数据包的MTU大小(更可能是pMTU大小)。
问题1:我真的不知道apache是否有任何知识。 它将处理TCP连接,并将其余部分留给操作系统TCP堆栈;)
Q2:碎片化。 数据包在路上被拒绝了,一个“再次发送,更小”被送回,服务器(不是apache – 这是ip stack)再次发送更小。
问题3:没有。 真的,我不认为,再次,apache处理的tcp堆栈在一个较低的水平,和MTU等是低得多。 服务器的TCP堆栈负责这个,如果设置了正确的设置(不是只需要“碎片需要”,而且是一个正确的更小的大小 – 参数你看它的TCP MSS)。
从技术上讲,这看起来像是一些破损的设备和/或一些破坏的TCP实现,因为SYN数据包上的MSS参数似乎包含大于允许的大小,或者发件人计算机只是忽略MSS值。
http://en.wikipedia.org/wiki/Maximum_segment_size是一个很好的开始参考。 看起来MTU发现失败(或结果被忽略),然后使用非标准大小。