【问题标题】:migrating Solaris to RH: network latency issue, tcp window size & other tcp parameters将 Solaris 迁移到 RH:网络延迟问题、tcp 窗口大小和其他 tcp 参数
【发布时间】:2010-06-08 09:05:10
【问题描述】:

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

  • 客户端连续向服务器发送 5 条消息(每条 32 字节)(相同的应用程序时间戳)。
  • 服务器回显消息。
  • 客户端接收回复并打印每个消息的往返时间。

在 Solaris 中,一切都很好:我在发送原始消息后大约 80 毫秒同时收到所有 5 个回复(客户端和服务器相距数千英里:我的 ping RTT 为 80 毫秒,一切正常)。

在 RH 中,前 3 条消息正常回显(它们在发送后 80 毫秒到达),但接下来的 2 条消息在 80 毫秒后到达(因此总共 160 毫秒 RTT)。

模式总是相同的。显然看起来像是 TCP 问题。

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

  1. 全局禁用 nagle 算法
  2. 将 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

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 发送得太晚,看起来服务器在做任何事情之前正在等待数据包 27 的 ACK。

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

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

我阅读了有关幻灯片窗口和缓冲区窗口的文档,并在我的套接字上使用了 java 中的 rcvBuffer 和 sendBuffer,但从未设法将这个 5888 值更改为其他任何值(我每次都直接使用 tcpdump 进行检查)。

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

我最终设法通过在 RH 上将“tcp_slow_start_after_idle”参数设置为 0 来解决部分问题,但它根本没有改变“win”参数。前 4 组 5 条消息存在同样的问题,在 tcpdump 中使用 TCP 重新传输和 TCP Dup ACK,然后所有后续 5 条消息组的问题都完全消失了。

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

我会继续研究,但非常感谢 TCP 专家的任何帮助!

【问题讨论】:

  • 跟踪与您的描述不符。 redhat 跟踪比 Solaris 花费的时间更少,所以我看不到延迟问题。回声也非常快(小于 1 毫秒),所以看起来这是在环回或 LAN 上完成的。
  • 无法比较左侧的时间戳(在 solaris 和 RH 之间),它们只是相对于每个盒子中收到第一个数据包的那一刻(我认为),这几乎可以随时。测试不是同时进行的。问题是在服务器上测量的接收 MSG 和回显回复之间的响应时间。在 solaris 上,所有回波都在 RH 上接收到第一个 msg (2.087500 - 2.085645 = 0.001855) 的大约 2 毫秒内发送,第 4 和第 5 个回波在 90 毫秒后发送 (2.171019 - 2.081163)

标签: java networking tcp solaris redhat


【解决方案1】:

看起来拥塞避免算法正在 Red Hat 机器上启动。

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

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

【讨论】:

  • 是的,这就是我关心的问题,我看到很多回显没有被客户端确认,并且想象一些机制会阻止服务器再发送任何东西,直到收到 ACK:它只发送收到 ACK 后的第 4 和第 5 个回声。只是不太清楚是什么导致了这种机制以及如何影响它。将玩拥塞控制,目前它是“立方”,将研究......谢谢!
  • @Bastien:尝试将其设置为“reno”(只是echo "reno" > /proc/sys/net/ipv4/tcp_congestion_control),看看您是否更喜欢这种行为。
猜你喜欢
  • 1970-01-01
  • 2013-01-01
  • 2013-09-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
相关资源
最近更新 更多