压测结束 10 分钟,ss -s 里 TIME_WAIT 还有 32418 条,新连接报 Cannot assign requested address,tcp_max_tw_buckets 是 262144。乍看像缓存或者权限的锅,追下去往往不是。
ss -tan state time-wait | wc -l sysctl net.ipv4.tcp_fin_timeout sysctl -w net.ipv4.tcp_tw_reuse=1
追下去是这么回事:主动关闭方要等 2MSL 才能释放四元组,默认 60 秒。短连接每秒几千个,回收速度赶不上产生速度,端口和 conntrack 一起被占住。
「TIME_WAIT 回收」这类改动最怕改一半,回滚脚本先准备好,再动生产。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。
线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。
权限不要一口气开到最大,先加到够用再往上试,范围小才好收。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
具体做法是,让服务端先关连接减少客户端侧 TIME_WAIT;客户端开 tcp_tw_reuse;把 tcp_fin_timeout 从 60 调到 15;能改长连接的地方优先改长连接。
验收就看一点,改成长连接后 TIME_WAIT 峰值从 3.2 万降到 200 以内,端口错误不再出现。
