压测跑到 8000 QPS 时客户端开始大量报 Cannot assign requested address,成功率掉到 60%。ss -s 显示 timewait 有 4 万条,本地端口范围是 32768 到 60999。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
sysctl net.ipv4.ip_local_port_range net.ipv4.tcp_tw_reuse ss -s sysctl -w net.ipv4.ip_local_port_range='1024 65535'
每个请求都新建连接,短连接关掉后进入 TIME_WAIT 占着四元组 60 秒。可用端口只有 2.8 万个,8000 QPS 撑不到 4 秒就耗尽。压测机和服务端在同一台机器上时端口还互相抢。这一点先确认清楚,后面就不用反复试。
「本地端口耗尽」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。把复现步骤压到三条以内,交给同事也能跑出来,才算真的定位清楚。
改动写完就同步给同事,下一个人踩同一个坑,成本还是你的。验证用真实数据走一遍,测试数据太干净,边界情况根本碰不到。
具体做法是,压测脚本改用长连接 打开 keep-alive 复用连接;确认 tcp_tw_reuse 打开 只对出方向生效;把端口范围扩到 1024 到 65535;分布式压测把连接分散到多台机器。
改完照着核一遍,8000 QPS 下成功率回到 99% 以上,TIME_WAIT 数量稳定不再增长。
