现代Linux系统能够打开的TCP连接数量的理论最大值是多少?

298
假设硬件性能无限,Linux 系统能否支持超过 65536 个开放的 TCP 连接?
我理解,短暂端口的数量(<65536)限制了一个本地 IP 到一个远程 IP 的一个端口上的连接数量。
元组 (本地 IP、本地端口、远程 IP、远程端口) 是唯一定义一个 TCP 连接的方式;这是否意味着如果其中多于一个参数是空闲的,可以支持超过 65K 个连接?例如,从多个本地 IP 到多个远程主机的单个端口号上的连接。
系统中是否有另一个 16 位限制?也许是文件描述符数量?
3个回答

447

一个监听端口可以同时接受多个连接。

通常会引用“64K”限制,但这是指每个客户端对每个服务器端口的限制,并需要澄清。

每个TCP/IP数据包基本上都有四个寻址字段。它们是:

source_ip source_port destination_ip destination_port
<----- client ------> <--------- server ------------>

TCP协议栈内部使用这四个字段作为复合键将数据包与连接(例如文件描述符)匹配。

如果一个客户端对同一目标的同一端口存在多个连接,那么其中三个字段将相同 - 只有source_port不同以区分不同的连接。 端口是16位数字,因此任何给定客户端对任何给定主机端口的最大连接数为64K。

但是,多个客户端可以各自对某些服务器端口拥有高达64K的连接,如果服务器具有多个端口或任意一个是多宿主,则可以进一步增加连接数。

因此,真正的限制是文件描述符。 每个单独的套接字连接都被赋予一个文件描述符,因此限制实际上是系统配置允许和处理的文件描述符数量。 最大限制通常超过300K,但可通过sysctl进行配置。

普通服务器的实际限制约为80K,例如单线程Jabber消息服务器。


4
如果你使用SO_REUSEADDR并且针对不同的目标IP地址,理论上可以拥有超过64K个输出连接。但内核内存限制可能会先阻止你。 - Darron
1
@Darron 我认为SO_REUSEADDR是用于服务器在重新启动时绑定的,对吗? - Will
7
sysctl限制是针对整个系统的,对吗?还有一个可以通过ulimit配置的限制,它限制了进程的最大文件描述符数量。这个默认值通常比300K少得多,通常为1024。 - pacoverflow
1
一个小技术细节:客户端机器也可以从路由器分配多个IP地址。这些地址都可以分配给单个MAC,或者该机器可以有多个物理网络接口以获取额外的IP地址。OP指定了1个IP,但对于其他人来说,不要排除更多的IP地址是很重要的。 - Kind Contributor
2
请注意,tcp_fin_timeout 默认情况下会阻塞相同的套接字(源、目标、端口组合)60 秒,这极大地减少了两个系统之间实际可用的 tcp 连接数量,如果连接经常断开和重新连接。可以通过允许在 TIME_WAIT 状态下重用(tcp_tw_reuse=1)套接字(不总是支持),或通过违反 TCP/IP 标准将此超时时间缩短到较低值来最小化此问题(通常仍然有效)。 - fgwaller
显示剩余3条评论

21

如果您正在考虑运行服务器并尝试决定一台机器可以提供多少连接,请阅读关于C10k问题以及同时为大量客户端提供服务可能涉及的潜在问题。


19
C10k已经十岁了,不再有趣。[阅读此文]了解如何解决C1024K问题。 - Chandranshu
1
@Chandranshu - 你是指https://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-3吗? - Mikko Rantalainen
1
@MikkoRantalainen - 是的。我认为现在有更好的基准测试可用。Phoenix团队已经将其推向了200万个同时连接。 - Chandranshu
4
@Chandranshu - 这里有一篇关于戴尔演示 1200 万连接的文章: https://mrotaru.wordpress.com/2013/06/20/12-million-concurrent-connections-with-migratorydata-websocket-server/。 - Mikko Rantalainen
2
相当多年前:Intel Atom D2700,2GB RAM,1.2M并发连接。我遇到的唯一问题是测试中的Windows框,它们在尝试DoS Intel Atom框时经常崩溃…… - Klaws
https://ieeexplore.ieee.org/abstract/document/8422993 -- C40m -- 不确定是否为Linux - John Carlson

13
如果您使用了原始套接字(SOCK_RAW)并在用户空间重新实现了TCP,那么在这种情况下,答案仅受到(本地地址、源端口、目标地址、目标端口)元组的数量限制(每个本地地址约为2^64)。
当然,保持所有这些连接的状态需要大量内存,并且我认为您必须设置一些iptables规则以使内核TCP堆栈不会因此而受到影响或代表您响应。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接