TIME_WAIT和CLOSE_WAIT状态过多的分析与解决

TIME_WAIT影响

  大量的TIME_WAIT进程,会消耗系统大量资源,导致程序异常。

  每一个tcp连接关闭后,主动关闭方会处于TIME_WAIT状态,最长超时时间2MSL,在这期间端口资源不会被释放。

  RFC 793中规定MSL为2分钟,实际由系统决定,通常在30-120s。

原理说明

  一个连接的建立与断开,正常过程至少需要来回7个包,分别是三次握手,四次挥手,才能完成。

image_1d9n60ljq1757ho21032k0j1fbr9.png-59.4kB

image_1d9olusia5vr1ss01rg5bchuu99.png-462.7kB

image_1d9n6th6n11m011up85uao4175q13.png-30.7kB
Each socket in TIME_WAIT consumes some memory in the kernel, usually somewhat less than an ESTABLISHED socket yet still significant. A sufficiently large number could exhaust kernel memory, or at least degrade performance because that memory could be used for other purposes. TIME_WAIT sockets do not hold open file descriptors (assuming they have been closed properly), so you should not need to worry about a "too many open files" error.

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

The socket also ties up that particular src/dst IP address and port so it cannot be reused for the duration of the TIME_WAIT interval. (This is the intended purpose of the TIME_WAIT state.) Tying up the port is not usually an issue unless you need to reconnect a with the same port pair. Most often one side will use an ephemeral port, with only one side anchored to a well known port. However, a very large number of TIME_WAIT sockets can exhaust the ephemeral port space if you are repeatedly and frequently connecting between the same two IP addresses. Note this only affects this particular IP address pair, and will not affect establishment of connections with other hosts.

  套接字绑定主机的 Src / Dst IP 地址和端口,因此在 TIME wait 间隔期间不能重复使用它。 (这是 TIME wait 状态的目的。) 连接端口一般不是问题,除非您需要重新连接到相同的端口对。 大多数情况下,主机会使用临时端口,连接固定的公有端口。 可是,如果频繁的连接两个相同的 IP 地址的临时端口,会消耗大量的 TIME_wait 套接字的临时端口空间。 请注意,这只影响这个特定的 IP 地址对,与其他主机建立连接的不受影响。

image_1d9n8pmdekv81jdn1j143ju1pid20.png-168.2kB

  TCP 连接必须经过时间 2MSL 后才真正释放掉占有资源Socket

  (2MSL 时间的用意:为了保证 A 发送的最后一个 ACK 报文段能够到达 B。

  防止 “已失效的连接请求报文段”出现在本连接中.

  A 在发送完最后一个 ACK 报文段后,需要经历2MSL时间后,就可以本连接持续的时间内所产生的所有报文段,都从网络中消失.这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段,从而保证了A发送的最后一个ACK报文顺利的到达B。)

  如果许多连接正在被快速打开和关闭,可能会引起大量的 TIME_WAIT 连接。
  这会引发端口资源或其他资源的消耗,如果达到上限,那么就会引发创建新连接的障碍。

  TIME_WAIT状态的连接过多导致系统端口资源耗尽

  大量的TIME_WAIT进程。简单来说,每一个tcp连接关闭后,主动关闭方都会保留这个连接一段时间,这个时间内,这个连接的状态是TIME_WAIT,端口资源不会被释放。这个超时时间为2*MSL。RFC 793中规定MSL为2分钟,实际由系统决定,通常在30-120s。这个网上有很多详细解释,这里不过多阐述。因为连接的关闭释放有一定时间,并不是程序运行完就立刻释放端口资源,所以当申请的连接进程较多的时候,端口资源就不够用了。系统默认可用的端口资源:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768 61000

解决办法:

1 扩大资源可用

  1、 扩大端口范围,linux是修改/etc/sysctl.conf

  net.ipv4.ip_local_port_range = 1024 65535

  2.#开启重用。允许将TIME-WAIT sockets重新用于新的TCP连接,默认为0

  net.ipv4.tcp_tw_reuse = 1

      最后再执行sysctl -p

2. 优化自己的系统,减少短连接次数

  因为tcp连接关闭后是有必要保留一段时间TIME_WAIT状态的,我们的目标不应该是简单的缩短TIME_WAIT时间,而是应该从根本上去优化我们的系统架构设计,减少不必要的短连接请求。

参考资料

引用:https://www.zybuluo.com/zhongdao/note/1466543

What is the cost of many TIME_WAIT on the server side? 在服务器端进行多次 TIME wait 的成本是多少?
https://stackoverflow.com/questions/1803566/what-is-the-cost-of-many-time-wait-on-the-server-side

http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html

(传输层)TCP协议
http://www.cnblogs.com/kzloser/articles/2582957.html

TIME_WAIT状态的连接过多导致系统端口资源耗尽问题(2)
https://www.cnblogs.com/wangsili/p/3958371.html

posted @ 2020-10-26 11:28  东方无解  阅读(1056)  评论(0编辑  收藏  举报