为什么服务器不会发送 SYN/ACK 数据包来响应 SYN 数据包

cod*_*key 48 linux web-server tcp

最近,我们发现了一个 TCP 连接问题,该问题主要限于浏览我们网站的 mac 和 Linux 用户。

从用户的角度来看,它表现为与我们网站的连接时间非常长(> 11 秒)。

我们已经设法追踪到这个问题的技术特征,但无法弄清楚它为什么会发生或如何解决它。

基本上,发生的事情是客户端的机器正在发送 SYN 数据包以建立 TCP 连接,而 Web 服务器收到它,但没有响应 SYN/ACK 数据包。在客户端发送了许多 SYN 数据包后,服务器最终以 SYN/ACK 数据包进行响应,并且连接的其余部分一切正常。

而且,当然,问题的关键是:它是间歇性的,不会一直发生(尽管它确实发生在 10-30% 的时间内)

我们使用 Fedora 12 Linux 作为操作系统,使用 Nginx 作为 Web 服务器。

Wireshark 分析截图

Wireshark 分析截图

更新:

在客户端上关闭窗口缩放阻止了问题的发生。现在我只需要一个服务器端分辨率(我们不能让所有客户端都这样做):)

最终更新:

解决方案是关闭我们服务器上可供公众访问的TCP 窗口缩放 TCP 时间戳

mcd*_*zle 16

我们遇到了完全相同的问题。只需禁用 TCP 时间戳即可解决问题。

sysctl -w net.ipv4.tcp_timestamps=0
Run Code Online (Sandbox Code Playgroud)

要使此更改永久化,请在/etc/sysctl.conf.

禁用 TCP Window Scale 选项时要非常小心。此选项对于通过 Internet 提供最大性能很重要。如果往返时间(与 ping 基本相同)超过 55 毫秒,则具有 10 兆位/秒连接的人将进行次优传输。

当同一个 NAT 后面有多个设备时,我们确实注意到了这个问题。我怀疑服务器可能会同时看到来自 Android 设备和 OSX 机器的时间戳,因为它们在时间戳字段中放置了完全不同的值。

  • 万一其他人通过我刚刚走下的同一个兔子洞结束:在关闭 TCP 时间戳或窗口缩放之前,这可能会对高流量链接产生严重的性能影响,请检查 tcp_tw_recycle 是否是您的问题:http ://stackoverflow.com/questions/8893888/dropping-of-connections-with-tcp-tw-recycle (5认同)

lav*_*lav 14

就我而言,以下命令修复了 Linux 服务器缺少 SYN/ACK 回复的问题:

sysctl -w net.ipv4.tcp_tw_recycle=0
Run Code Online (Sandbox Code Playgroud)

我认为这比禁用 TCP 时间戳更正确,因为 TCP 时间戳对于高性能(PAWS、窗口缩放等)很有用。

上的文档tcp_tw_recycle明确指出不建议启用它,因为许多 NAT 路由器会保留时间戳,因此 PAWS 会启动,因为来自同一 IP 的时间戳不一致。

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this
          option is not recommended for devices communicating with the
          general Internet or using NAT (Network Address Translation).
          Since some NAT gateways pass through IP timestamp values, one
          IP can appear to have non-increasing timestamps.  See RFC 1323
          (PAWS), RFC 6191.
Run Code Online (Sandbox Code Playgroud)

  • 就我而言,“net.ipv4.tcp_tw_recycle”是真正的原因。谢谢。 (2认同)
  • tcp_tw_recycle 已在最近的内核中删除。还有其他类似的解决方案吗?@nephtes 暗示禁用时间戳会损害性能。 (2认同)

use*_*238 5

只是想知道,但为什么对于 SYN 数据包(第 539 帧;被接受的数据包),“信息”列中缺少 WS 和 TSV 字段?

WS 是TCP 窗口缩放,TSV 是时间戳值。它们都可以在 tcp.options 字段下找到,如果它们存在,Wireshark 仍然应该显示它们。也许客户端 TCP/IP 堆栈在第 8 次尝试时重新发送了不同的 SYN 数据包,这就是它突然被确认的原因?

你能给我们提供第 539 帧的内部值吗?SYN/ACK 是否总是针对未启用 WS 的 SYN 数据包?


akr*_*mer 1

这是侦听 TCP 套接字在积压已满时的行为。

Ngnix 允许在配置中设置 backlog 参数来监听: http://wiki.nginx.org/HttpCoreModule#listen

听 80 backlog=num

尝试将 num 设置为大于默认值的值,例如 1024。

我不保证完整的侦听队列实际上是您的问题,但这是首先要检查的好事情。