Description
TIME_WAIT与端口耗尽
谁会进入time_wait : 谁主动发起关闭(先发fin包)连接谁就进入该状态,一般为client端。
当tcp连接的某端关闭 tcp 连接时,内存中会维护一个小的 控制块, 用来记录最近关闭连接的 ip和port 。这类信息会维持的时间为 2MSL(报文段的最大生存时间的2倍,RFC793定义了MSL为2分钟,Linux设置成了30s),以确保这段时间内不会创建具有相同 ip:port 的新连接(以避免新连接中接收到旧连接的脏包)。
看了手边的机器centos 7 cat /proc/sys/net/ipv4/tcp_fin_timeout
为60s,源码中的定义:2
This specifies how many seconds to wait for a final FIN packet before the socket is forcibly closed.
There is a hardwired constant, TCP_TIMEWAIT_LEN (defined to 60s), which is used in a number of places. There is no way to change it without recompilation.
TCP_TIMEWAIT_LEN == msl ? 无法更改
#define TCP_FIN_TIMEOUT TCP_TIMEWAIT_LEN
TCP_FIN_TIMEOUT 可更改,默认为TCP_TIMEWAIT_LEN
如果没有修改过该值,那么可以通过 tcp_fin_timeout = 2 * MSL
推断(不严谨)出MSL的大小,该值是可以改变的,但是无法通过该值来改变MSL,MSL是硬编码在内核中的,不止该地方用到MSL。
client 每次连接到 server 上时,都会获得一个新的 source-port(会占用client的一个port),以实现连接的唯一性。可用源宽口是有限的(默认3w左右,可通过参数ip_local_port_range
查看/修改),而且在 2MSL 秒(60)内无法连接无法重用,连接率就被限制在 30000/60 = 500 次/秒。理论上,连接率不高于 500 次/秒,就可确保不会遇到 TIME_WAIT 端口耗尽问题。
ip_local_port_range
端口范围,linux 中默认为 32768 61000
所以最多可以建立 61000 - 32768 = 28232 个连接
The /proc/sys/net/ipv4/ip_local_port_range defines the local port range that is used by TCP and UDP traffic to choose the local port. You will see in the parameters of this file two numbers: The first number is the first local port allowed for TCP and UDP traffic on the server, the second is the last local port number. For high-usage systems you may change its default parameters to 32768-61000 -first-last.