将Solaris迁移到RH:网络延迟问题,tcp窗口大小&其他tcp参数

时间:2010-06-08 09:05:11

标签: java networking tcp solaris redhat

我有一个客户端/服务器应用程序(Java),我正在从Solaris迁移到RH Linux。 自从我开始在RH中运行它以来,我注意到一些与延迟相关的问题。 我设法找出了这样的问题:

  • 客户端将一行(相同的应用程序时间戳)中的5条消息(每个32字节)发送到服务器。
  • 服务器回声消息。
  • 客户收到回复并打印每个消息的往返时间。
在Solaris中,一切都很顺利:我在同一时间收到所有5个回复,大约在发送原始邮件后80毫秒(客户端和服务器相距几千英里远:我的ping RTT是80毫秒,一切正常)

在RH中,前3个消息正常回显(它们在发送后80ms到达),但是后面的2个消息在80ms后到达(因此总共160ms RTT)。

模式总是一样的。显然看起来像TCP问题。

在我的solaris盒子上,我之前使用2个特定选项配置了tcp堆栈:

  1. 全局禁用nagle算法
  2. 将tcp_deferred_acks_max设为0
  3. 在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
    

    REDHAT

     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被发送到TOO LATE,看起来服务器在做任何事情之前都在等待数据包27的ACK。

    在我看来,这是最可能的原因......

    然后我意识到Solaris上的“Win”参数是不同的。 RH转储:Solaris上为50400,RH上为5888。这是另一个提示......

    我阅读了关于幻灯片窗口和文档的文档。缓冲区窗口,并与rcvBuffer& amp;我的套接字上的java中的sendBuffer,但从未设法将此5888值更改为其他任何内容(我每次都使用tcpdump直接检查)。

    有人知道怎么做吗?我很难获得确切的信息,因为在某些情况下,我可能需要绕过“自动协商”等等......

    我最终设法通过在RH上将“tcp_slow_start_after_idle”参数设置为0来仅部分摆脱我的初始问题,但它根本没有改变“win”参数。对于前4组5条消息,同样的问题是TCP重传& tcpdump中的TCP Dup ACK,然后所有后续5组消息的问题都完全消失了。

    对我来说,它似乎不是一个非常干净和/或通用的解决方案。我真的想在两种操作系统下重现完全相同的条件。

    我会继续研究,但是非常感谢来自TCP大师的任何帮助!

1 个答案:

答案 0 :(得分:1)

看起来拥塞避免算法在Red Hat盒子上蠢蠢欲动。

请注意,从数据包26开始,服务器已经看到并确认了客户端的所有内容,但客户端只确认了服务器的初始SYN - 它尚未确认服务器消息的任何 。另请注意,数据包27再次启动,是客户端确认服务器的前两批数据(数据包19和22)。

Red Hat机箱使用哪种拥塞控制算法? (/proc/sys/net/ipv4/tcp_congestion_control) - 你可以尝试切换到其他可用的那个。