我有一个客户机/服务器应用程序(Java),我正在从Solaris迁移到RHLinux。
自从我开始在rh中运行它以来,我注意到一些与延迟相关的问题。
我设法找出了看起来像这样的问题:
客户机一行(同一应用程序时间戳)向服务器发送5条消息(每条32字节)。
服务器回显消息。
客户端接收回复并打印每个消息的往返时间。
在Solaris中,一切都很好:我同时得到所有5个回复,大约在发送原始消息后80毫秒(客户机和服务器相距几千英里:我的ping rtt是80毫秒,一切正常)。
在rh中,前3条消息被正常地回送(它们在发送后80毫秒到达),但是接下来的2条消息在80毫秒之后到达(所以总共160毫秒RTT)。
模式总是一样的。显然是TCP问题。
在我的solaris机器上,我以前用2个特定选项配置了tcp堆栈:
全局禁用Nagle算法
将tcp_deferred_acks_max设置为0
在rh上,不可能全局禁用nagle,但我在所有应用程序的套接字(tcp_nodelay)上都禁用了它。
因此,我开始使用tcpdump(在服务器机器上)并比较两种输出:
Solaris:

 22 2.085645    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 23 2.085680    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=133 Win=50400 Len=0
 24 2.085908    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 25 2.085925    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=155 Win=50400 Len=0
 26 2.086175    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 27 2.086192    server         client          TCP      6006 > 56150 [ACK] Seq=106 Ack=177 Win=50400 Len=0
 28 2.086243    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=106 Ack=177 Win=50400 Len=21    "MSG_1 ECHO"
 29 2.086440    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 30 2.086454    server         client          TCP      6006 > 56150 [ACK] Seq=127 Ack=199 Win=50400 Len=0
 31 2.086659    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=127 Ack=199 Win=50400 Len=21    "MSG_2 ECHO"
 32 2.086708    client         server          TCP      56150 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 33 2.086721    server         client          TCP      6006 > 56150 [ACK] Seq=148 Ack=221 Win=50400 Len=0
 34 2.086947    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=148 Ack=221 Win=50400 Len=21    "MSG_3 ECHO"
 35 2.087196    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=169 Ack=221 Win=50400 Len=21    "MSG_4 ECHO"
 36 2.087500    server         client          TCP      6006 > 56150 [PSH, ACK] Seq=190 Ack=221 Win=50400 Len=21    "MSG_5 ECHO"
 37 2.165390    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 38 2.166314    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=190 Win=66588 Len=0
 39 2.364135    client         server          TCP      56150 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

红帽:
 17 2.081163    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=111 Ack=106 Win=66672 Len=22    "MSG_1 RCV"
 18 2.081178    server         client          TCP      6006 > 55879 [ACK] Seq=106 Ack=133 Win=5888 Len=0
 19 2.081297    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=106 Ack=133 Win=5888 Len=21 "MSG_1 ECHO"
 20 2.081711    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=133 Ack=106 Win=66672 Len=22    "MSG_2 RCV"
 21 2.081761    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=155 Ack=106 Win=66672 Len=22    "MSG_3 RCV"
 22 2.081846    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=127 Ack=177 Win=5888 Len=21 "MSG_2 ECHO"
 23 2.081995    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=148 Ack=177 Win=5888 Len=21 "MSG_3 ECHO"
 24 2.082011    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=177 Ack=106 Win=66672 Len=22    "MSG_4 RCV"
 25 2.082362    client         server          TCP      55879 > 6006 [PSH, ACK] Seq=199 Ack=106 Win=66672 Len=22    "MSG_5 RCV"
 26 2.082377    server         client          TCP      6006 > 55879 [ACK] Seq=169 Ack=221 Win=5888 Len=0
 27 2.171003    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=148 Win=66632 Len=0
 28 2.171019    server         client          TCP      6006 > 55879 [PSH, ACK] Seq=169 Ack=221 Win=5888 Len=42 "MSG_4 ECHO + MSG_5 ECHO"
 29 2.257498    client         server          TCP      55879 > 6006 [ACK] Seq=221 Ack=211 Win=66568 Len=0

所以,我得到了对rh的确认:包28发送得太晚了,看起来服务器在做任何事情之前都在等待包27的确认。
在我看来这是最有可能的原因…
然后我意识到在solaris和rh转储中,“win”参数是不同的:在solaris中为50400,在rh中为5888。这是另一个提示…
我阅读了有关幻灯片窗口和缓冲区窗口的文档,并在我的套接字中使用Java中的RCVBase&SeDeBuffs进行了播放,但从未成功地将这5888个值更改为其他任何东西(我每次用TCPDUMP直接检查)。
有人知道怎么做吗?我很难得到确切的信息,因为在某些情况下,有“自动协商”可能需要绕过,等等…
通过在rh上将“tcp_slow_start_after_idle”参数设置为0,我最终只成功地部分解决了最初的问题,但它根本没有更改“win”参数。前4组5条消息也存在同样的问题,tcp重传和tcp dup ack在tcpdump中,随后所有5条消息组的问题都消失了。
对我来说,这似乎不是一个非常干净和/或通用的解决方案。我真的很想在两个操作系统下复制完全相同的条件。
我将继续研究,但任何来自TCP专家的帮助都将非常感谢!

最佳答案

看起来拥塞避免算法正在被红帽箱攻击。
注意,从数据包26开始,服务器已经看到并确认了来自客户端的所有内容,但是客户端只确认了服务器的初始syn—它还没有确认服务器的任何消息。还要注意,包27再次启动,它是客户机确认服务器的前两批数据(包19和22)。
Red Hat Box使用哪种拥塞控制算法?(/proc/sys/net/ipv4/tcp_congestion_control)-您可以尝试切换到其他可用选项之一。

09-06 09:41