69

假设有一个客户端与服务器建立了很多短期连接。

如果客户端关闭连接,客户端会有很多端口处于TIME_WAIT状态。由于客户端用完了本地端口,因此无法快速进行新的连接尝试。

如果服务器关闭连接,我会TIME_WAIT在服务器端看到很多s。然而,这有什么害处吗?客户端(或其他客户端)可以继续尝试连接,因为它永远不会用完本地端口,并且TIME_WAIT服务器端的状态数量会增加。最终会发生什么?有什么不好的事情发生吗?(减速、崩溃、连接断开等)

请注意,我的问题不是“目的是TIME_WAIT什么?” 但是“如果TIME_WAIT服务器上有这么多状态会发生什么?” 我已经知道在 TCP/IP 中关闭连接时会发生什么以及为什么TIME_WAIT需要状态。我不是想解决它,只是想知道它的潜在问题是什么。

简单地说,让我们说netstat -nat | grep :8080 | grep TIME_WAIT | wc -lprints 100000。会发生什么?操作系统的网络堆栈会变慢吗?“打开的文件太多”错误?或者,只是没有什么可担心的?

4

6 回答 6

66

每个套接字都TIME_WAIT消耗内核中的一些内存,通常比一个ESTABLISHED套接字少一些,但仍然很重要。足够大的数字可能会耗尽内核内存,或者至少会降低性能,因为该内存可以用于其他目的。 TIME_WAIT套接字不保存打开的文件描述符(假设它们已正确关闭),因此您不必担心“打开的文件过多”错误。

套接字还绑定了该特定src/ dstIP 地址和端口,因此它不能在TIME_WAIT间隔期间重复使用。(这是该TIME_WAIT状态的预期目的。)除非您需要使用相同的端口对重新连接端口,否则绑定端口通常不是问题。大多数情况下,一侧将使用临时端口,只有一侧锚定到众所周知的端口。TIME_WAIT但是,如果您在相同的两个 IP 地址之间反复频繁地连接,那么大量的套接字可能会耗尽临时端口空间。请注意,这只影响这个特定的 IP 地址对,不会影响与其他主机建立连接。

于 2009-12-06T02:56:34.593 回答
15

每个连接都由一个元组(服务器 IP、服务器端口、客户端 IP、客户端端口)标识。至关重要的是,TIME_WAIT连接(无论是在服务器端还是在客户端)每个都占用这些元组之一。

使用TIME_WAIT客户端的 s ,很容易看出为什么不能建立更多的连接 - 你没有更多的本地端口。但是,同样的问题也适用于服务器端——一旦单个客户端TIME_WAIT的状态为 64k 连接,它就不能再接受来自该客户端的任何连接,因为它无法区分旧连接和旧连接。新连接 - 两个连接都由同一个元组标识。在这种情况下,服务器应该只将s 发送回来自该客户端的新连接尝试。RST

于 2009-11-26T22:58:39.960 回答
13

迄今为止的发现:

即使服务器使用系统调用关闭了套接字,如果它进入TIME_WAIT状态,它的文件描述符也不会被释放。文件描述符将在 TIME_WAIT 状态消失后(即 2*MSL 秒后)释放。因此,过多的 TIME_WAIT 可能会导致服务器进程出现“打开的文件过多”错误。

我相信 OS TCP/IP 堆栈已经使用适当的数据结构(例如哈希表)实现,因此 TIME_WAIT 的总数不应影响 OS TCP/IP 堆栈的性能。只有拥有处于 TIME_WAIT 状态的套接字的进程(服务器)才会受到影响。

于 2009-11-26T14:25:25.333 回答
2

如果您有很多从许多不同客户端 IP 到服务器 IP 的连接,您可能会遇到连接跟踪表的限制。

查看:

sysctl net.ipv4.netfilter.ip_conntrack_count
sysctl net.ipv4.netfilter.ip_conntrack_max

在所有 src ip/port 和 dest ip/port 元组中,跟踪表中只能有 net.ipv4.netfilter.ip_conntrack_max 。如果达到此限制,您将在日志中看到一条消息“nf_conntrack:表已满,正在丢弃数据包。” 并且服务器不会接受新的传入连接,直到跟踪表中再次有空间。

在临时端口用完之前,此限制可能会影响您很久。

于 2016-08-29T11:48:51.983 回答
0

在我的场景中,我运行了一个重复调度文件的脚本,我的产品进行了一些计算并向客户端发送响应,即客户端正在进行重复的 http 调用以获取每个文件的响应。当大约 150 个文件被安排在我的服务器中的套接字端口时处于 time_wait 状态,并且在打开 http 连接的客户端中引发异常,即

 Error : [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted

结果是我的应用程序挂起。我不知道线程可能处于等待状态或发生了什么,但我需要终止所有进程或重新启动我的应用程序以使其再次工作。

我尝试将等待时间减少到 30 秒,因为默认情况下它是 240 秒,但它不起作用。

所以基本上整体影响是至关重要的,因为它使我的应用程序无响应

于 2018-05-02T05:33:08.293 回答
-1

看起来服务器可能会用完端口来分配传入连接(在现有的 TIMED_WAIT 期间)——这是 DOS 攻击的一个案例。

于 2009-11-26T13:09:09.577 回答