服务器端的许多TIME_WAIT的成本是多less?
假设有一个客户端与服务器build立了很多短暂的连接。
如果客户端closures连接,则在客户端将有许多处于TIME_WAIT
状态的端口。 由于客户端用完了本地端口,因此不可能迅速build立新的连接。
如果服务器closures连接,我会在服务器端看到很多TIME_WAIT
。 但是,这是否有害? 客户端(或其他客户端)可以继续进行连接尝试,因为它永远不会从本地端口中耗尽,并且服务器端的TIME_WAIT
状态数将增加。 最终会发生什么? 有什么不好发生? (减速,崩溃,连接断开等)
请注意,我的问题不是“ TIME_WAIT
的目的是什么? 但是“如果服务器上有这么多的TIME_WAIT
状态会发生什么? 我已经知道在TCP / IP中closures连接时会发生什么,以及为什么需要TIME_WAIT
状态。 我不是在试图麻烦 – 拍摄它,而是想知道它有什么潜在的问题。
简而言之,让我们说netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
打印100000
。 会发生什么? O / Snetworking堆栈是否减速? “打开的文件太多”错误? 或者,没什么可担心的?
TIME_WAIT
每个套接字都占用内核中的一些内存,通常比ESTABLISHED
套接字less一些,但仍然很重要。 数量足够大可能会耗尽内核内存,或者至less会降低性能,因为该内存可能用于其他目的。 TIME_WAIT
套接字不保存打开的文件描述符(假设它们已经被正确closures),所以你不需要担心“太多打开的文件”错误。
该套接字还将特定的src
/ dst
IP地址和端口关联起来,因此在TIME_WAIT
时间间隔内不能重新使用。 (这是TIME_WAIT
状态的预期目的。)捆绑端口通常不是问题,除非需要使用相同的端口对重新连接。 大多数情况下,一边将使用一个短暂的港口,只有一边锚定到一个众所周知的港口。 但是,如果在同一个两个IP地址之间反复频繁地连接,则有大量的TIME_WAIT
套接字可能会耗尽临时端口空间。 请注意,这只影响这个特定的IP地址对,并不会影响与其他主机build立连接。
迄今为止的发现:
即使服务器使用系统调用closures套接字,如果它进入TIME_WAIT状态,它的文件描述符也不会被释放。 文件描述符将在TIME_WAIT状态消失后(即2 * MSL秒后)释放。 因此,在服务器进程中,太多的TIME_WAIT可能会导致“打开的文件太多”错误。
我相信O / S TCP / IP堆栈已经实现了正确的数据结构(如散列表),所以TIME_WAIT的总数不应该影响O / S TCP / IP堆栈的性能。 只有拥有TIME_WAIT状态的套接字的进程(服务器)将受到影响。
每个连接都由元组(服务器IP,服务器端口,客户端IP,客户端端口)标识。 关键的是, TIME_WAIT
连接(无论是在服务器端还是在客户端)都占用了这些元组之一。
通过在客户端的TIME_WAIT
,很容易看出为什么你不能再build立连接 – 你没有更多的本地端口。 但是,同样的问题也适用于服务器端 – 一旦它在单个客户端的 TIME_WAIT
状态下有64k连接,就不能接受来自该客户端的更多连接,因为它无法区分旧连接和新的连接 – 两个连接都由相同的元组标识。 在这种情况下,服务器应该只发送RST
到来自该客户端的新连接尝试。
如果从许多不同的客户端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:table full,丢包”。 并且服务器将不会再接受新的传入连接,直到跟踪表中有空间。
短暂的端口用完之前,这个限制可能会打到你。
它看起来像服务器可以只是用尽端口分配传入的连接(在现有TIMED_WAITs期间) – 一个DOS攻击的情况。