一台机器理论最多能支撑多少个TCP连接

对于服务器来说,最大支持的并发连接是多少呢?

其实,最先受限制的是内核文件打开数,不过这个可以通过修改内核参数来避免。
一条TCP连接是由一个四元组组成的。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,对于我们这台Nginx Server来说,它的IP和端口是固定的。cp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的。它可能建立的最大的连接数是2的32次方(ip数)×2的16次方(port数)。这是2.8*10的14次方的一个大数字,两百万亿!!

Linux上除了监听80以外,还可以监听其它的端口,例如Mysql的3306, Redis的6339,当然所有65535个端口你都可以用来监听一遍。这样理论上线就到了2的32次方(ip数)×2的16次方(port数)×2的16次方(服务器port数)个。感兴趣你可以算一下,这个基本相当于无穷个了。

不过理想和实际总是会有差距的,因为Linux每维护一条TCP连接都要花费资源。处理连接请求,保活,数据的收发时需要消耗一些CPU,维持TCP连接主要消耗内存。我们题目的问题是考虑最大多少个连接,所以我们先不考虑数据的收发。那么TCP在静止的状态下,就不怎么消耗CPU了,主要消耗内存。而Linux上内存是有限的。

我们今天先直接把结论抛出来,一条TCP连接如果不发送数据的话,消耗内存是3.3K左右。如果有数据发送,需要为每条TCP分配发送缓存区,大小受你的参数net.ipv4.tcp_wmem配置影响,默认情况下最小是4K。但比如wmem/rmem设置, MSS协商, 是否有conntrack, 窗口拥塞, 滑动窗口等,TCPIP太多需要考虑的情况了,如果不考虑skb包的大小多少, 单纯只是算一条TCP连接所需要的数据结构占多少内存, 倒是可以估算出来比较精确的值。如果发送结束,缓存区消耗的内存会被回收。简单的实验数据如下图:
max-tcp-connect.jpg

假设你只保持连接不发送数据,那么你服务器可以建立的连接最大数量 = 你的内存/3.3K。 假如是4GB的内存,那么大约可接受的TCP连接数量是100万左右。

这个例子里,我们考虑的前提是在一个进程下hold所有的服务器端连接。而在实际中的项目里,为了收发数据方便,很多网络IO模型还会为TCP连接再创建一个线程或协程。拿最轻量的golang来说,一个协程栈也需要2KB的内存开销。

结论
一台机器最大究竟能支持多少个网络连接?这个问题里其实埋了坑,导致无数的英雄好汉被困惑不解。就和树上九只鸟打死一只还剩几只的问题一样,没有和你说清楚树上是真鸟,还是假鸟。也没有说枪是有声还是无声的。

标签: none

添加新评论