TIME_WAIT 为什么要等 2MSL?谁会留下它?大量堆积会怎样?这篇量出本机 TIME_WAIT 的真实时长,让同一个源端口马上重连被拒绝,把临时端口真的用光,最后看 SO_LINGER 0 能不能绕开它。
net.inet.tcp.msl: 15000 net.inet.tcp.fin_timeout: 60000 客户端(端口 51963)close 之后 0.0 秒第一次看到 TIME_WAIT,31.4 秒时这一行消失——TIME_WAIT 持续约 31.3 秒 = 2 × MSL(2 × 15 s = 30 s)
本机 MSL 15 秒,TIME_WAIT 持续 2MSL,实测约 31 秒。
同一个源端口 51999、同一个服务器,不设 SO_REUSEADDR:绑定失败:Address already in use 同一个源端口 51999、同一个服务器,设 SO_REUSEADDR:绑定成功,connect 失败:Address already in use
占住四元组,防止旧连接的迟到包混进新连接:TIME_WAIT 期间同一个源端口不能连同一个服务器(即使设了 SO_REUSEADDR 也不行)。
客户端先 close:TIME_WAIT 里,服务端一侧(本地端口 = 服务端口)0 个,客户端一侧(本地是临时端口)500 个 服务端先 close:TIME_WAIT 里,服务端一侧(本地端口 = 服务端口)500 个,客户端一侧(本地是临时端口)0 个 所以“服务器上有大量 TIME_WAIT”往往是因为服务器主动关闭了连接(如 HTTP 短连接 Connection: close、超时踢人);客户端的 TIME_WAIT 则会占用客户端的临时端口
谁先 close 谁留下:服务器主动关闭,TIME_WAIT 在服务器;客户端主动关闭,TIME_WAIT 在客户端并占用临时端口。
连续建立 / 关闭短连接:成功 15696 次后第 15697 次失败:[Errno 49] Can't assign requested address(用时 5.8 秒) 此刻 netstat 里和这个服务端口有关的 TIME_WAIT 有 15696 个(临时端口范围一共 16384 个) 失败之后立刻再试 200 次:成功 0 次、失败 200 次——端口快用完时,随机挑到已被占用的端口就失败,所以不是“一个都没剩”才失败,而是越到后面失败越频繁 不再建立新连接,等 TIME_WAIT 过期:31 秒后只剩不到 50 个(最早的一批是 5.8 秒前建立的;每个 TIME_WAIT 持续约 30 秒)
客户端短连接太多时,临时端口会被 TIME_WAIT 占满,新连接报 Can't assign requested address,要等 TIME_WAIT 过期才恢复。
客户端 正常 close():建立并关闭 500 个连接后,和这个服务端口有关的 TIME_WAIT 有 500 个 客户端 SO_LINGER(开,0 秒)后 close():建立并关闭 500 个连接后,和这个服务端口有关的 TIME_WAIT 有 0 个 linger 0 把 TIME_WAIT 省掉了,但代价是:对方没读完的数据会丢,迟到的旧包也可能被新连接收到;更常见的正确做法是让客户端主动关闭 / 用连接池 / 调大临时端口范围
SO_LINGER 0 用 RST 代替 FIN,不留 TIME_WAIT,但会丢未读数据。更好的做法是复用连接。