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。

posted on 2026-09-09 21:34  小镇-做题家  阅读(32)  评论(0)    收藏  举报

导航