关于linux:一台机器最多能撑多少个TCP连接-今天掰扯清楚

46次阅读

共计 3000 个字符,预计需要花费 8 分钟才能阅读完成。

在网络开发中,我发现有很多同学对一个根底问题始终是没有彻底搞明确。那就是一台机器最大到底能反对多少个网络连接?我想我有必要独自发一篇文章来好好说一下这个问题。很多同学看到这个问题的第一反馈是 65535。起因是:“据说端口号最多有 65535 个,那长连贯就最多放弃 65535 个了”。是这样的吗?还有的人说是应该受 TCP 连贯里四元组的空间大小限度,这样算起来就是十分十分大的一个数字了。这两个答案都对,也都不对。

其实要想把这个问题搞清楚,最最最要害的中央在于要把 TCP 连贯的两端里的角色分分明 - 客户端和服务器端。你手头的任何一台服务器,个别状况下都即是服务器,又是客户端。例如对于你的开发的后端接口,对于用户来说你是服务器端。但你得申请 Redis、Mysql 去获取数据,这时候又变成了客户端。如果不把这台机器作为客户端和服务器端两种角色拆开来了解,你将永远被这个问题困惑上来。所以本文别离从客户端、服务端两块来开展聊聊。

客户端

当初咱们独自来说客户端,当一台机器作为客户端的时候,到底能反对多少个 TCP 连贯?空嘴说没有啥意思,咱们间接用代码来试试。

1. 小试牛刀

开始试验之前咱们先来 check 下手头机器上的端口数量的配置

$ sysctl -a | grep ip_local_port_range
net.ipv4.ip_local_port_range = 15000    65000

通过上述内核参数的输入看到内核凋谢了 50000 个端口能够供 TCP 连贯应用。接下来是一段看起来长,但其实非常简单的 TCP 客户端连贯的代码。用它来连贯你的任意一个 TCP Server,比方 Nginx、Redis 啥的都能够。

我通过这段代码对我的某台机器上的 Nginx 发动了连贯

$ php client1.php 某台服务器 IP 80

通过 netstat 命令看到连贯数量稳步回升,但当回升到 5W 的时候,呈现了一条报错

socket_connect() 失败的起因是:Cannot assign requested address

回头想想咱们的 ip_local_port_range 参数值,65000-15000 就只凋谢了 5 万个。其实是超过这个限度了。这个时候咱们仿佛能够初步得出一个相论断.当 Linux 作为客户端建设连贯的时候,最大连贯数量是受内核参数 net.ipv4.ip_local_port_range 限度 而 ip_local_port_range 是可配置的,最大实践范畴是 0 -65535

进阶

如果这个时候你置信了我下面的论断的话,就又被我带了沟里了。为什么这么说,让咱们来看上面的试验。

首先通过 ifconfig 命令看到我的机器上有两块网卡,每块网卡都曾经配置好了一个 ip。

接着咱们批改一下第一个试验的代码,在发动连贯之前容许应用 socket_bind 来绑定 ip。

接下来咱们别离启动两个控制台,别离执行一下代码。其中 10.143.x.x 和 10.153.x.x 是试验用机的两个网卡 ip。

$ php client1.php 10.143.x.x 某台服务器 IP 80
$ php client2.php 10.153.x.x 某台服务器 IP 80

这个时候通过 ss 命令监控本机的 ESTABLISH 连贯,发现曾经冲破 5 万,并向 10 万迫近了。

$ ss -n | grep ESTAB | wc –l
90005 

当初咱们终于能够得出更为正确的论断了,对于有 1 个 Ip 的客户端来说,受限于 ip\_local\_port\_range 参数,也受限于 65535。但单 Linux 能够配置多个 ip,有几个 ip,最大理论值就翻几倍

多张网卡不是必须的。即便只有一张网卡,也能够配置多 ip。k8s 就是这么干的,在 k8s 里,一台物理机上能够部署多个 pod。但每一个 pod 都会被调配一个独立的 ip,所以齐全不必放心物理机上部署了过多的 pod 而影响你用的 pod 里的 TCP 连贯数量。在 ip 给你的那一刻,你的 pod 就和其它利用隔离开了。

服务端

咱们当初在来回头思考服务器端。对于服务器来说,最大反对的并发连贯是多少呢?就有人开始可恶地糊涂了:“服务器端实践也是端口限度吗?”。好,假如如果受影响的话,那咱们的 Nginx 服务器只监听了一个 80 端口。那 Nginx 只能承受一个 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。如果发送完结,缓存区耗费的内存会被回收具体的剖析过程敬请期待接下来的另一篇文章。

假如你只放弃连贯不发送数据,那么你服务器能够建设的连贯最大数量 = 你的内存 /3.3K。 如果是 4GB 的内存,那么大概可承受的 TCP 连贯数量是 100 万左右。

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

论断

一台机器最大到底能反对多少个网络连接?这个简略的问题里其实埋了坑,导致有数的英雄好汉被迷惑不解。就和树上九只鸟打死一只还剩几只的问题一样,没有和你说分明树上是真鸟,还是假鸟。也没有说枪是有声还是无声的。通过明天的剖析,置信你终于能够扬眉吐气把这个问题踩在脚下摩擦了。

  • TCP 连贯的客户端机:每一个 ip 可建设的 TCP 连贯实践受限于 ip\_local\_port\_range 参数,也受限于 65535。但能够通过配置多 ip 的形式来加大本人的建设连贯的能力。
  • **TCP 连贯的服务器机:每一个监听的端口尽管理论值很大,但这个数字没有实际意义。最大并发数取决你的内存大小,每一条静止状态的 TCP 连贯大概须要吃 3

.3K 的内存。**


我的公众号是「开发内功修炼」,在这里我不是单纯介绍技术实践,也不只介绍实践经验。而是把实践与实际联合起来,用实际加深对实践的了解、用实践进步你的技术实际能力。欢送你来关注我的公众号,也请分享给你的好友~~~

正文完
 0