0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一台客户端机器最多能发起多少条TCP连接?

jf_ro2CN3Fa 来源:稀土掘金 2023-10-30 15:02 次阅读

之前有一位读者向我诉苦,有次面试,好不容易(今年行情大家都懂的)熬到到技术终面,谁知道面试官突然放个大招问他:一台服务器最大能支持多少条 TCP 连接,把他直接给问懵逼了。。。。(请自行脑补那尴尬的场面与气氛)。

所以,今天就来讨论一下这个问题。

一台服务器最大能打开的文件数

限制参数

我们知道在Linux中一切皆文件,那么一台服务器最大能打开多少个文件呢?Linux上能打开的最大文件数量受三个参数影响,分别是:

fs.file-max (系统级别参数):该参数描述了整个系统可以打开的最大文件数量。但是root用户不会受该参数限制(比如:现在整个系统打开的文件描述符数量已达到fs.file-max ,此时root用户仍然可以使用ps、kill等命令或打开其他文件描述符)。

soft nofile(进程级别参数):限制单个进程上可以打开的最大文件数。只能在Linux上配置一次,不能针对不同用户配置不同的值。

fs.nr_open(进程级别参数):限制单个进程上可以打开的最大文件数。可以针对不同用户配置不同的值。

这三个参数之间还有耦合关系,所以配置值的时候还需要注意以下三点:

如果想加大soft nofile,那么hard nofile参数值也需要一起调整。如果因为hard nofile参数值设置的低,那么soft nofile参数的值设置的再高也没有用,实际生效的值会按照二者最低的来。

如果增大了hard nofile,那么fs.nr_open也都需要跟着一起调整(fs.nr_open参数值一定要大于hard nofile参数值)。如果不小心把hard nofile的值设置的比fs.nr_open还大,那么后果比较严重。会导致该用户无法登录,如果设置的是*,那么所有用户都无法登录。

如果加大了fs.nr_open,但是是用的echo "xxx" > ../fs/nr_open命令来修改的fs.nr_open的值,那么刚改完可能不会有问题,但是只要机器一重启,那么之前通过echo命令设置的fs.nr_open值便会失效,用户还是无法登录。所以非常不建议使用echo的方式修改内核参数!!!

调整服务器能打开的最大文件数示例

假设想让进程可以打开100万个文件描述符,这里用修改conf文件的方式给出一个建议。如果日后工作里有类似的需求可以作为参考。

vim/etc/sysctl.conf

fs.file-max=1100000//系统级别设置成110万,多留点buffer
fs.nr_open=1100000//进程级别也设置成110万,因为要保证比hardnofile大

使上面的配置生效sysctl -p

vim/etc/security/limits.conf

//用户进程级别都设置成100完
softnofile1000000
hardnofile1000000

一台服务器最大能支持多少连接

我们知道TCP连接,从根本上看其实就是client和server端在内存中维护的一组【socket内核对象】(这里也对应着TCP四元组:源IP、源端口、目标IP、目标端口),他们只要能够找到对方,那么就算是一条连接。那么一台服务器最大能建立多少条连接呢?

由于TCP连接本质上可以理解为是client-server端的一对socket内核对象,那么从理论上将应该是【2^32 (ip数) * 2^16 (端口数)】条连接(约等于两百多万亿)。

但是实际上由于受其他软硬件的影响,我们一台服务器不可能能建立这么多连接(主要是受CPU和内存限制)。

如果只以ESTABLISH状态的连接来算(这些连接只是建立,但是不收发数据也不处理相关的业务逻辑)那么一台服务器最大能建立多少连接呢?以一台4GB内存的服务器为例!

这种情况下,那么能建立的连接数量主要取决于【内存的大小】(因为如果是)ESTABLISH状态的空闲连接,不会消耗CPU(虽然有TCP保活包传输,但这个影响非常小,可以忽略不计)。

我们知道一条ESTABLISH状态的连接大约消耗【3.3KB内存】,那么通过计算得知一台4GB内存的服务器,【可以建立100w+的TCP连接】(当然这里只是计算所有的连接都只建立连接但不发送和处理数据的情况,如果真实场景中有数据往来和处理(数据接收和发送都需要申请内存,数据处理便需要CPU),那便会消耗更高的内存以及占用更多的CPU,并发不可能达到100w+)。

上面讨论的都是进建立连接的理想情况,在现实中如果有频繁的数据收发和处理(比如:压缩、加密等),那么一台服务器能支撑1000连接都算好的了,所以一台服务器能支撑多少连接还要结合具体的场景去分析,不能光靠理论值去算。抛开业务逻辑单纯的谈并发没有太大的实际意义。

服务器的开销大头往往并不是连接本身,而是每条连接上的数据收发,以及请求业务逻辑处理!!!

一台客户端机器最多能发起多少条连接

我们知道客户端每和服务端建立一个连接便会消耗掉client端一个端口。一台机器的端口范围是【0 ~ 65535】,那么是不是说一台client机器最多和一台服务端机器建立65535个连接呢(这65535个端口里还有很多保留端口,可用端口可能只有64000个左右)?

由TCP连接的四元组特性可知,只要四元组里某一个元素不同,那么就认为这是不同的TCP连接。所以需要分情况讨论:

情况一】、如果一台client仅有一个IP,server端也仅有一个IP并且仅启动一个程序,监听一个端口的情况下,client端和这台server端最大可建立的连接条数就是 65535 个。

因为源IP固定,目标IP和端口固定,四元组中唯一可变化的就是【源端口】,【源端口】的可用范围又是【0 ~ 65535】,所以一台client机器最大能建立65535个连接。

情况二】、如果一台client有多个IP(假设客户端有 n 个IP),server端仅有一个IP并且仅启动一个程序,监听一个端口的情况下,一台client机器最大能建立的连接条数是:n * 65535 个。

因为目标IP和端口固定,有 n 个源IP,四元组中可变化的就是【源端口】+ 【源IP】,【源端口】的可用范围又是【0 ~ 65535】,所以一个IP最大能建立65535个连接,那么n个IP最大就能建立 n * 65535个连接了。

以现在的技术,给一个client分配多个IP是非常容易的事情,只需要去联系你们网管就可以做到。

情况三】、如果一台client仅有一个IP,server端也仅有一个IP但是server端启动多个程序,每个程序监听一个端口的情况下(比如server端启动了m个程序,监听了m个不同端口),一台client机器最大能建立的连接数量为:65535 * m。

源IP固定,目标IP固定,目标端口数量为m个,可变化的是源端口,而源端口变化范围是【0 ~ 65535】,所以一台client机器最大能建立的TCP连接数量是 65535 * m个。

其余情况类推,但是客户端的可用端口范围一般达不到65535个,受内核参数net.ipv4.ip_local_port_range限制,如果要修改client所能使用的端口范围,可以修改这个内核参数的值。

所以,不光是一台server端可以接收100w+个TCP连接,一台client照样能发出100w+个连接。

其他

三次握手里socket的全连接队列长度由参数net.core.somaxconn来控制,默认大小是128,当两台机器离的非常近,但是建立连接的并发又非常高时,可能会导致半连接队列或全连接队列溢出,进而导致server端丢弃握手包。然后造成client超时重传握手包(至少1s以后才会重传),导致三次握手连接建立耗时过长。我们可以调整参数net.core.somaxconn来增加去按连接队列的长度,进而减小丢包的影响

有时候我们通过 ctrl + c方式来终止了某个进程,但是当重启该进程的时候发现报错端口被占用,这种问题是因为【操作系统还没有来得及回收该端口,等一会儿重启应用就好了】

client程序在和server端建立连接时,如果client没有调用bind方法传入指定的端口,那么client在和server端建立连接的时候便会自己随机选择一个端口来建立连接。一旦我们client程序调用了bind方法传入了指定的端口,那么client将会使用我们bind里指定的端口来和server建立连接。所以不建议client调用bind方法,bind函数会改变内核选择端口的策略

publicstaticvoidmain(String[]args)throwsIOException{
SocketChannelsc=SocketChannel.open();
//客户端还可以调用bind方法
sc.bind(newInetSocketAddress("localhost",9999));
sc.connect(newInetSocketAddress("localhost",8080));
System.out.println("waiting..........");
}

在Linux一切皆文件,当然也包括之前TCP连接中说的socket。进程打开一个socket的时候需要创建好几个内核对象,换一句直白的话说就是打开文件对象吃内存,所以Linux系统基于安全角度考虑(比如:有用户进程恶意的打开无数的文件描述符,那不得把系统搞奔溃了),在多个位置都限制了可打开的文件描述符的数量。

内核是通过【hash表】的方式来管理所有已经建立好连接的socket,以便于有请求到达时快速的通过【TCP四元组】查找到内核中对应的socket对象。

在epoll模型中,通过红黑树来管理epoll对象所管理的所有socket,用红黑树结构来平衡快速删除、插入、查找socket的效率。

相关实际问题

网络开发中,很多人对一个基础问题始终没有彻底搞明白,那就是一台机器最多能支撑多少条TCP连接。不过由于客户端和服务端对端口使用方式不同,这个问题拆开来理解要容易一些。

注意,这里说的是客户端和服务端都只是角色,并不是指某一台具体的机器。例如对于我们自己开发的应用程序来说,当他响应客户端请求的时候,他就是服务端。当他向MySQL请求数据的时候,他又变成了客户端。

"too many open files" 报错是怎么回事,该如何解决

你在线上可能遇到过too many open files这个错误,那么你理解这个报错发生的原理吗?如果让你修复这个错误,应该如何处理呢?

因为每打开一个文件(包括socket),都需要消耗一定的内存资源。为了避免个别进程不受控制的打开了过多文件而让整个服务器奔溃,Linux对打开的文件描述符数量有限制。如果你的进程触发到内核的限制,那么"too many open files" 报错就产生了。

可以通过修改fs.file-max 、soft nofile、fs.nr_open这三个参数的值来修改进程能打开的最大文件描述符数量。

需要注意这三个参数之间的耦合关系!

一台服务端机器最大究竟能支持多少条连接

因为这里要考虑的是最大数,因此先不考虑连接上的数据收发和处理,仅考虑ESTABLISH状态的空连接。那么一台服务端机器上最大可以支持多少条TCP连接?这个连接数会受哪些因素的影响?

在不考虑连接上数据的收发和处理的情况下,仅考虑ESTABLISH状态下的空连接情况下,一台服务器上最大可支持的TCP连接数量基本上可以说是由内存大小来决定的。

四元组唯一确定一条连接,但服务端可以接收来自任意客户端的请求,所以根据这个理论计算出来的数字太大,没有实际意义。另外文件描述符限制其实也是内核为了防止某些应用程序不受限制的打开【文件句柄】而添加的限制。这个限制只要修改几个内核参数就可以加大。

一个socket大约消耗3kb左右的内存,这样真正制约服务端机器最大并发数的就是内存,拿一台4GB内存的服务器来说,可以支持的TCP连接数量大约是100w+。

一条客户端机器最大究竟能支持多少条连接

和服务端不同的是,客户端每次建立一条连接都需要消耗一个端口。在TCP协议中,端口是一个2字节的整数,因此范围只能是0~65535。那么客户单最大只能支持65535条连接吗?有没有办法突破这个限制,有的话有哪些办法?

客户度每次建立一条连接都需要消耗一个端口。从数字上来看,似乎最多只能建立65535条连接。但实际上我们有两种办法破除65535这个限制。

方式一,为客户端配置多IP 方式二,分别连接不同的服务端

所以一台client发起百万条连接是没有任何问题的。

做一个长连接推送产品,支持1亿用户需要多少台机器

假设你是系统架构师,现在老板给你一个需求,让你做一个类似友盟upush这样的产品。要在服务端机器上保持一个和客户端的长连接,绝大部分情况下连接都是空闲的,每天也就顶多推送两三次左右。总用户规模预计是1亿。那么现在请你来评估一下需要多少台服务器可以支撑这1亿条长连接。

对于长连接推送模块这种服务来说,给客户端发送数据只是偶尔的,一般一天也就顶多一两次。绝大部分情况下TCP连接都是空闲的,CPU开销可以忽略。

再基于内存来考虑,假设服务器内存是128G的,那么一台服务器可以考虑支持500w条并发。这样会消耗掉大约不到20GB内存用来保存这500w条连接对应的socket。还剩下100GB以上的内存来应对接收、发送缓冲区等其他的开销足够了。所以,一亿用户,仅仅需要20台服务器就差不多够用了!

编辑:黄飞

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8997

    浏览量

    85134
  • Server
    +关注

    关注

    0

    文章

    90

    浏览量

    23994
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1348

    浏览量

    78969
  • 端口
    +关注

    关注

    4

    文章

    952

    浏览量

    32000

原文标题:面试官:一台服务器最大能支持多少条 TCP 连接?问倒一大片。。。

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    Linux网络编程-TCP客户端如何获取要连接的服务IP?

    本篇介绍了在TCP通信中,客户端通过UDP广播,实现自动获取服务的IP地址,并进行TCP连接的具体方法,并通过代码实现,来测试此方案是实际
    的头像 发表于 09-27 08:56 3544次阅读
    Linux网络编程-<b class='flag-5'>TCP</b><b class='flag-5'>客户端</b>如何获取要<b class='flag-5'>连接</b>的服务<b class='flag-5'>端</b>IP?

    求助,关于ESP32C3 TCP客户端连接断线问题求解

    ESP32C3开启AP模式做TCP服务器,手机做客户端连接服务器;超过默认最大连接数(5)以后,即使有部分客户端断开了,也无法再
    发表于 06-27 07:54

    如何同时在ESP8266上运行TCP客户端TCP服务?

    我们是 esp8266 的长期用户,并在该芯片上运行数千家庭自动化类别的现场设备。然而,个小小的限制阻碍了我们开发些更有趣和创新的产品。 要求:我们需要同时运行 TCP
    发表于 07-08 08:26

    求助!用labview的TCP传输协议传输的图片不能在客户端实时...

    求助!我编了用labviewTCP传输协议进行图像采集传输的TCP客户端和服务客户端和服务同时在同
    发表于 12-04 17:09

    labview TCP客户端

    最近在做个labview 客户端测试小程序,服务器采用MFC编写,客户端采用TCP侦听函数,通信可以连接,数据也正确,但是服务器
    发表于 06-30 23:15

    一台电脑两点之间的TCP通信,客户端收不到数据

    一台电脑,两点之间的TCP通信,客户端收不到数据,主要的报错如图(试了很多个例程也是这样,所以感觉不是程序的问题),求解~~弄了天了(ps:我的lv是试用版会不会有影响到部分功能无法
    发表于 10-06 01:22

    tcp或udp创建的聊天室,一台电脑可以创建多个客户端

    一台电脑不是只有个IP吗,想问问有什么办法可以在一台电脑创建多个客户端
    发表于 07-13 15:51

    请问申请连接函数tcp_connect()只能由客户端发起吗?

    请教大神:申请连接函数tcp_connect()只能是由客户端发起的吗?小弟在这里有点迷惑,恳请大神指教~
    发表于 07-01 00:59

    基于Socket开发TCP传输客户端

    1 程序界面设计 TCP客户端在上位机开发中应用很广,大多数情况下,上位机软件都是作为TCP客户端来与PLC或其他服务器进行通信的。
    发表于 07-02 06:33

    CH395作为TCP客户端连接电脑TCP服务的时间很长怎么解决?

    CH395作为TCP客户端,电脑作为TCP服务,第连接时很快就能
    发表于 10-14 06:09

    当WiFi信号变低时,服务器和客户端之间的TCP通信丢失,如何使客户端重新连接

    大家好, 当 WiFi 信号变低时,服务器和客户端之间的 TCP 通信丢失,比如超过 -80dBm。客户端断开连接,它就无法重新
    发表于 05-15 07:31

    JAVA教程之TCP客户端

    JAVA教程之TCP客户端,很好的JAVA的资料,快来学习吧
    发表于 04-11 17:28 7次下载

    ESP8266作为TCP客户端连接TCP服务器和测试的实例资料说明

    本文档的主要内容详细介绍的是ESP8266作为TCP客户端连接TCP服务器和测试的实例资料说明。
    发表于 06-06 17:51 8次下载
    ESP8266作为<b class='flag-5'>TCP</b><b class='flag-5'>客户端</b><b class='flag-5'>连接</b><b class='flag-5'>TCP</b>服务器和测试的实例资料说明

    一台Linux服务器最多能支撑多少个TCP连接

    【导读】:单 Linux 服务器可以支撑多少个 TCP 连接? 关于这个问题,我想很多客户端的同学都不怎么了解,甚至于很多服务器开发也没有特意的关注。 那么这个承载数到底取决了什么,
    的头像 发表于 12-29 11:13 5144次阅读

    基于LwIP的TCP客户端设计

    篇我们基于LwIP协议栈的RAW API实现了TCP服务器的简单应用,接下来节我们来实现T
    的头像 发表于 12-14 15:12 2229次阅读
    基于LwIP的<b class='flag-5'>TCP</b><b class='flag-5'>客户端</b>设计