设置 TIME_WAIT TCP
Posted
技术标签:
【中文标题】设置 TIME_WAIT TCP【英文标题】:Setting TIME_WAIT TCP 【发布时间】:2010-09-25 03:01:34 【问题描述】:我们正在尝试调整一个通过 TCP 接受消息并使用 TCP 进行一些内部消息传递的应用程序。在负载测试时,我们注意到响应时间显着降低(然后完全停止),因为系统同时发出更多请求。在此期间,我们看到很多 TCP 连接处于 TIME_WAIT
状态,有人建议将 TIME_WAIT
环境变量从默认的 60 秒降低到 30。
从what I understand 开始,TIME_WAIT
设置实质上是设置 TCP 资源在连接关闭后再次可供系统使用的时间。
我不是“网络人”,对这些事情知之甚少。我需要该链接帖子中的很多内容,但要“简化”一点。
我想我明白为什么TIME_WAIT
的值不能设置为0,但可以安全地设置为5 吗? 10个呢?什么决定了这个值的“安全”设置?
为什么这个值的默认值为 60?我猜比我聪明很多的人有充分的理由选择它作为合理的默认值。
关于覆盖此值的潜在风险和收益,我还应该了解哪些信息?
【问题讨论】:
另外你也不想设置太高:***.com/questions/1803566/… 【参考方案1】:一个 TCP 连接由元组指定(源 IP、源端口、目标 IP、目标端口)。
会话关闭后出现 TIME_WAIT 状态的原因是,网络中可能仍有实时数据包正在发送给您(或来自您的数据包可能会请求某种响应)。如果您要重新创建相同的元组并且其中一个数据包出现,它将被视为您的连接的有效数据包(并且可能由于排序而导致错误)。
所以 TIME_WAIT 时间一般设置为数据包最大年龄的两倍。此值是您的数据包在网络丢弃它们之前允许到达的最长时间。
这保证了,在您被允许使用相同的元组创建连接之前,属于该元组先前化身的所有数据包都将失效。
这通常决定了您应该使用的最小值。最大数据包使用期限由网络属性决定,例如卫星寿命高于 LAN 寿命,因为数据包还有很长的路要走。
【讨论】:
如何确定“最大数据包年龄”?这个设置是操作系统、网络上的东西还是一些软件设置?顺便说一句,“生成”大多数这些连接的代码是我们没有来源的第三方平台。感谢您的好评! 它的真实名称是最大段生命周期,MSL。不确定您是否可以在 Windows 中更改它,或者即使您应该更改它 - 它应该根据网络特征进行设置。我认为 Windows 将其设置为 120 秒。所有 TCP 参数都在 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters 中。Not sure you can change this in Windows or even if you should - it's meant to be set based on network characteristics. Windows sets it to 120s, I think.
☹ 你绝对可以change it in Linux 和 120 是方式太长了。我还没有测试确认,但看起来有这么长的延迟会使大多数路由器上的 P2P 变得不必要。
@Synetech,只有在您循环进行 大量 次会话时才会出现问题。否则,超时时的会话清理应该处理它。我相信即使是 torrent 也会保持会话打开一段时间,如果可能的话,可以重复使用它们,当然,这取决于客户端。
@paxdiablo,是的,应该。我用我确实喜欢的“更新、更好”的 DIR-625 替换了我的旧 DI-524,但从那时起,每当我仅仅打开一个 torrent 客户端时,我的连接终止(没有 HTTP、NTP、ping,什么都没有)。除了路由器,其他都一样。我检查了 TCPView,发现 torrent 客户端有很多延迟连接。几乎立即关闭它让我再次冲浪,所以显然路由器已经不堪重负。减少延迟会有所帮助(我已经大大减少了#connections)。 (此外,Chrome 会打开无数连接,即使是 NTP 也无济于事。)【参考方案2】:
通常,只有发出“主动关闭”的端点应该进入 TIME_WAIT 状态。因此,如果可能,让您的客户端发出主动关闭,这会将 TIME_WAIT 留在客户端而不是服务器上。
请参阅此处:http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html 和 http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ 了解详细信息(后者还解释了为什么由于协议设计未考虑 TIME_WAIT 而并非总是可行)。
【讨论】:
好点,服务器仍然需要等待来自其 FIN 的 ACK,但这应该花费更少的时间。发起者关闭会话也是一种很好的做法,因为通常只有它知道何时结束。 第二个链接已过期。试试这个:web.archive.org/web/20170521010646/http://www.isi.edu/touch/…【参考方案3】:Pax 关于 TIME_WAIT 的原因是正确的,以及为什么您应该小心降低默认设置。
更好的解决方案是更改用于套接字原始端的端口号。一旦你这样做了,你就不会真正关心等待单个套接字的时间了。
对于监听套接字,您可以使用 SO_REUSEADDR 来允许监听套接字绑定,尽管 TIME_WAIT 套接字位于周围。
【讨论】:
我会支持任何以“Pax 是正确的”开头的答案。 :-) 对于具有数千个活动套接字的非常活跃的机器,实际上可以在 TIME_WAIT 中绑定所有临时端口。一旦发生这种情况,您将无法再打开任何连接,直到某些套接字完成等待。减少 TIME_WAIT 持续时间会有很大帮助。正如 Len Holgate 所提到的,如果可能的话,最好让客户端启动主动关闭,因为这完全避免了服务器的 TIME_WAIT 职责。 默认情况下,原始端口号会自动变化,这无助于服务器的 TIME_WAIT 状态。正确的解决方案是确保客户端先关闭。【参考方案4】:在 Windows 中,你 can change 它 through the registry:
; Set the TIME_WAIT delay to 30 seconds (0x1E)
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\TCPIP\Parameters]
"TcpTimedWaitDelay"=dword:0000001E
【讨论】:
设置 tcp_fin_timeout 不会影响 time_wait - 这是一个常见的误解。这是完全不同的事情(显然是 FIN 超时)。许多指南等都指向此设置,但它们是错误的。查看 tcp.h,您会发现它是硬编码的 (Linux)。【参考方案5】:设置 tcp_reuse 比更改 time_wait 更有用,只要您有参数(内核 3.2 及更高版本,不幸的是,这会取消所有 RHEL 和 XenServer 版本的资格)。
删除该值,尤其是对于连接 *** 的用户,可能会导致在出站连接上不断重建代理隧道。使用低于默认 Linux 配置的默认 Netscaler (XenServer) 配置,Chrome 有时必须重新创建代理隧道多达十几次才能检索一个网页。不重试的应用程序,例如 Maven 和 Eclipse P2,只会失败。
该参数的最初动机(避免重复)被一个 TCP RFC 冗余,该 RFC 指定在所有 TCP 请求中包含时间戳。
【讨论】:
【参考方案6】:我一直在使用具有 20 个线程的测试程序对服务器应用程序(在 linux 上)进行负载测试。
在 959,000 个连接/关闭周期中,我有 44,000 个失败的连接和 TIME_WAIT 中的数千个套接字。
我在关闭调用之前将 SO_LINGER 设置为 0,在随后的测试程序运行中没有连接失败,并且 TIME_WAIT 中的套接字少于 20 个。
【讨论】:
而且您还冒着丢失数据的风险。这不是正确的解决方案。 SO_LINGER 不是什么好东西。正确的解决方案是确保客户端首先关闭,通常通过在客户端进行连接池并编写服务器以处理每个连接的多个请求。实际上就像 HTTP 1.1。 我的回答应该更清楚。我不主张将逗留时间设置为 0,只是指出我在 Windows 上观察到的问题。在linux上这个问题没有发生。因此,它取决于系统,并且可能取决于处于活动状态的系统设置。 它不依赖于系统。像这样重置套接字会丢失所有传输中的数据。【参考方案7】:TIME_WAIT 可能不是罪魁祸首。
int listen(int sockfd, int backlog);
根据 Unix Network Programming Volume1,积压被定义为已完成连接队列和未完成连接队列的总和。
假设积压为 5。如果您有 3 个已完成的连接(ESTABLISHED 状态)和 2 个未完成的连接(SYN_RCVD 状态),并且还有另一个 SYN 连接请求。 TCP 堆栈只是忽略 SYN 数据包,知道它会在其他时间重新传输。这可能会导致降级。
至少这是我一直在阅读的内容。 ;)
【讨论】:
我很确定积压仅用于尚未达到 ESTABLISHED 的连接;一旦他们拥有,他们就会从队列中移除;他们只会阻塞更多的传入连接,直到 (SYN,SYN/ACK,ACK) 握手完成,基本上是在服务器从 accept() 返回时。 (-1) 不,listen backlog 纯粹是针对未完全建立的连接;即它们已到达 TCP/IP 堆栈但尚未被“接受”。如果您的侦听积压太小,那么如果连接进来的速度快于接受连接的速度,您的服务器将拒绝连接。 一个小误会。 “已完成的连接队列。此队列包含完成三向握手的每个连接的条目。套接字处于 ESTABLISHED 状态。每次调用 accept() 都会删除队列的最前面的条目。” sean.de/Solaris/soltune.html @LenHolgate 一个未被接受的连接仍然可以完全建立,并且这样的连接进入积压队列。对于不完整的连接,还有其他队列。是否会拒绝或忽略会溢出积压的传入连接取决于系统:Windows 拒绝,Unix 等忽略。以上是关于设置 TIME_WAIT TCP的主要内容,如果未能解决你的问题,请参考以下文章