ip_local_port_range 和五元组限制并客户端并发
“TCP 最大只能有 65535 个会话”这个说法不准确。65535 是端口号的上限,不是整台机器 TCP 会话总数的上限。
一个 TCP 会话由五元组唯一确定:
源 IP + 源端口 + 目标 IP + 目标端口 + 协议(TCP)
65535 限制从哪里来
TCP 报文中的源端口和目标端口字段都是 16 位:
2^16 = 65536
端口范围:0~65535
其中端口 0 通常不用于正常连接,所以常说最多 65535 个端口。
但一个端口不等于只能对应一个全局 TCP 会话。只要五元组不同,连接就可以同时存在。
哪些场景真的会遇到端口限制
1. 单个客户端连接同一个服务端地址
例如:
客户端:10.0.0.10
服务端:10.0.0.20:443
客户端不断建立连接:
10.0.0.10:32768 -> 10.0.0.20:443
10.0.0.10:32769 -> 10.0.0.20:443
10.0.0.10:32770 -> 10.0.0.20:443
因为源 IP、目标 IP、目标端口都固定,只能靠源端口区分连接。
这时上限不是严格的 65535,而是客户端的临时端口范围。Linux 查看:
sysctl net.ipv4.ip_local_port_range
典型输出:
net.ipv4.ip_local_port_range = 32768 60999
可用临时端口约为:
60999 - 32768 + 1 = 28232
因此,这个客户端对同一个目标 IP:端口通常只能同时维持约 2.8 万条主动连接。
查看端口范围:
cat /proc/sys/net/ipv4/ip_local_port_range
可能出现的错误:
Cannot assign requested address
或者应用报告:
address already in use
connect: cannot assign requested address
2. NAT/SNAT 网关端口耗尽
这是最容易真正碰到“约 65535”限制的场景。
假设大量内网客户端都通过一个公网 IP 访问同一个目标:
10.0.0.11:* \
10.0.0.12:* ---> NAT 公网 IP 1.2.3.4:* ---> 8.8.8.8:443
10.0.0.13:* /
NAT 转换后,源 IP都变成:
1.2.3.4
为了区分连接,NAT 需要分配不同的公网源端口:
1.2.3.4:10001 -> 8.8.8.8:443
1.2.3.4:10002 -> 8.8.8.8:443
对于固定的:
公网源 IP + 目标 IP + 目标端口 + TCP
理论上最多大约有 6.4 万个端口映射,实际数量通常更少,因为:
-
部分端口被保留或占用
-
NAT 实现的端口分配范围可能更小
-
连接关闭后还可能处于
TIME_WAIT -
conntrack 表可能提前耗尽
-
NAT 设备自身可能设置会话上限
解决方法通常包括:
-
增加 SNAT 公网 IP
-
使用连接池和长连接
-
减少短连接
-
将流量分散到不同目标 IP
-
扩大 NAT 端口池
-
检查 conntrack 容量
3. 反向代理连接固定后端
例如 Nginx、HAProxy 或 Envoy:
Nginx IP -> 固定后端 IP:8080
如果代理只使用一个源 IP,并为每个请求建立一条后端 TCP 连接,那么代理到固定后端地址也受临时源端口数量限制。
例如:
192.168.1.10:32768 -> 192.168.1.20:8080
...
192.168.1.10:60999 -> 192.168.1.20:8080
可能只有约 2.8 万条并发或尚未释放的连接。
常见改善方式:
-
启用 upstream keepalive
-
使用连接池
-
给代理配置多个源 IP
-
增加后端 IP
-
扩大临时端口范围
4. 服务端监听一个端口
服务端监听:
0.0.0.0:443
并不表示只能接收 65535 个连接。
不同客户端可以使用相同的源端口:
10.0.0.1:50000 -> 10.0.0.20:443
10.0.0.2:50000 -> 10.0.0.20:443
10.0.0.3:50000 -> 10.0.0.20:443
它们的源 IP 不同,所以五元组不同。
因此,单个服务端端口理论上可以承载远超 65535 条连接。服务端更可能先受到这些资源限制:
-
文件描述符
ulimit -n -
系统文件句柄上限
-
内存
-
socket 缓冲区
-
accept 队列
-
CPU
-
conntrack 表
-
应用自身最大连接数
查看限制:
ulimit -n
sysctl fs.file-max
sysctl fs.nr_open
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
sysctl net.netfilter.nf_conntrack_max
统计当前 TCP 连接:
ss -s
统计 443 端口已建立连接:
ss -Hnt state established '( sport = :443 )' | wc -l
TIME_WAIT 为什么会导致端口不足
大量短连接关闭后,主动关闭方通常会进入 TIME_WAIT:
ss -Hnt state time-wait | wc -l
查看具体连接:
ss -Hnt state time-wait
如果客户端持续访问同一个目标,大量临时端口被 TIME_WAIT 占用,就可能暂时无法建立新连接。
但要注意:
TIME_WAIT 多 ≠ 一定端口耗尽
需要按本地地址、远端地址和远端端口统计,确认是不是同一组连接消耗了临时端口。
例如:
ss -Hnt state established,time-wait \
| awk '{print $4, $5}' \
| sort | uniq -c | sort -nr | head
准确结论
| 场景 | 是否受约 65535 限制 |
|---|---|
| 服务端监听一个端口,接收不同客户端连接 | 否,可远超 65535 |
| 单个源 IP 连接固定目标 IP:端口 | 是,受临时源端口范围限制 |
| NAT 单公网 IP访问固定目标 IP:端口 | 是,可能接近 65535 |
| 连接不同目标 IP | 可分别复用源端口 |
| 连接相同目标 IP 的不同端口 | 可分别复用源端口 |
| 使用多个源 IP | 每个源 IP都可提供一套端口空间 |
大量短连接处于 TIME_WAIT |
可能加速临时端口耗尽 |
最准确的表达是:
单个源 IP、针对同一个目标 IP:端口、使用 TCP 时,最大并发连接数受到可用源端口数量限制;整台服务器的 TCP 总连接数并不限制为 65535。
浙公网安备 33010602011771号