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

dd096f698d34c6d6b4e8f66f1f0eb478.gif关注公众号,回复“1024”获取2TB学习资源!

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

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

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

限制参数

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

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

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

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

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

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

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

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

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

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

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

使上面的配置生效sysctl -p

vim /etc/security/limits.conf// 用户进程级别都设置成100完  
soft nofile 1000000  
hard nofile 1000000

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

我们知道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函数会改变内核选择端口的策略

public static void main(String[] args) throws IOException {  SocketChannel sc = SocketChannel.open();  // 客户端还可以调用bind方法  sc.bind(new InetSocketAddress("localhost", 9999));  sc.connect(new InetSocketAddress("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台服务器就差不多够用了!

作者:文攀 

来源:juejin.cn/post/7162824884597293086

8ae940222c62013d1262ced73a2804d9.png

c3454adabd698c35f83a2f765136cce0.png

推荐阅读 点击标题可跳转

服务器爆了,你却连如何快速定位错误都不知道?

再见 Win 11 !下一代操作系统来了。。。

专为懒人设计!一款功能强大的 Docker 管理工具

又一款内存数据库横空出世,比 Redis 性能更强

谷歌中国大裁员赔偿 N+9?不,结果比这更离谱

ChatGPT 正式发布 API!所有企业都可接入

推荐一款超高颜值 Markdown 编辑器,爱了!

1231068672778470aac40915827c6206.png

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。点在看支持我们吧!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/8200.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

tkinter实现chatGPT对话深色界面

chatGPT官网经常会因为系统升级等情况而不能用, 有时候响应也特别慢, 于是API排上用场. 之前写了一个简易的命令窗式的问答, 能多轮对话, 还能保存对话, 但是输入很不方便. 回头一看额度才用了4毛钱, 于是在api免费期限还剩一个一个月的时候写了一个对话界面, 目前只是单轮对…

chatgpt赋能python:Python主界面设计指南

Python主界面设计指南 Python主界面的设计对于初学者和专业开发人员来说都是至关重要的。在正式开始你的Python编程之前,一个友好、简单、易于理解的界面设计可以使学习曲线变得更加平缓。在这篇文章中,我们将探讨一些Python主界面的设计指南和最佳实践…

SpringBoot 整合 ChatGPT API 项目实战

体验到了ChatGPT的强大之后,那么我们会想,如果我们想基于ChatGPT开发一个自己的聊天机器人,这个能搞定吗? ChatGPT平台已经为技术提供了一个入口了,很简单的就是实现了。 一、准备工作 (1)已成功…

SpringBoot 整合ChatGPT API项目实战

准备工作 (1)已成功注册 OpenAI 的账号。 (2)创建 API KEY,这个 API KEY 是用于 HTTP 请求身份验证的,可以创建多个。 注意这个创建之后需要马上复制好保存,关闭弹框之后就看不到了。 &#xf…

ChatGPT官方鉴别器紧急发布!当代自相矛盾,不想却遭遇群嘲

ChatGPT到处“造假”作弊,现在搞得OpenAI官方都坐不住了。 就在今天,OpenAI紧急发布官方打假工具:基于GPT打造,打开网页就能用。 好家伙,这岂不是真以己之矛攻己之盾了? 一经上线,那叫一个火…

别被chatGPT戏弄了

官方的介绍是,这一模型可以与人类进行谈话般的交互,可以回答追问,连续性的问题,承认其回答中的错误,指出人类提问时的不正确前提,拒绝回答不适当的问题。 科学愉快地玩耍了一下 不设限的问答(加完前置条件后…

如何使用charles代理转发请求

1.安装charles,打开菜单Proxy 打开 Proxy Setting 这个配置,勾选 Enable transparent HTTP proxying 如下图所示,手机端直接代理设置成你的电脑ip(cmd里ipconfig可以看),端口用默认代理端口8888即可 2. 开…

.NetCore HttpClient Proxy 设置全局代理

.NetCore HttpClient Proxy 设置全局代理 环境 .net6.0,使用的是 HttpClient 在Program.cs里面 service.AddHttpClient<HttpClientHelper>();重点是在 HttpClientHelpe 的构造函数里面设置 构造函数会接受来自Program.cs里面注入的 HttpClient 因此我可以直接对其进行配置…

HttpClient5如何设置代理

文章目录 说明原始HttpClient代理HttpClient总结 说明 在这篇文章中会对HttpClient5如何进行代理进行说明&#xff0c;我的HttpClient版本是5.2.1。在进行代理之前请先准备好代理服务器。 原始HttpClient 下面是没有进行代理设置的代码&#xff0c;尝试去访问openai接口 Tes…

开启postman的代理

开启代理&#xff0c;拦截postman的请求&#xff0c;得到具体请求参数 设置中的settings>proxy>添加代理地址与端口

window 流量全局代理

准备工作 proxifierv2rayN(连接远程代理) / fiddler (本地数据捕获) 声明 此文章用于全局流量捕获&#xff0c;技术无罪&#xff0c;请合理合法的使用。 用途 早些时候写过抓取钉钉网课视频连接&#xff0c;钉钉可以设置代理服务器&#xff0c;但是有一些软件不可以设置代…

使用本地网络搭建代理,绕过公司网络屏蔽

公司屏蔽了网易云&#xff0c;斗鱼等 &#xff0c;想用代理绕过屏蔽&#xff0c;达到在公司也可以听歌看视频的目的。 因为穷&#xff0c;没有服务器&#xff0c;就想用家里的电脑的网络转发流量。 按着以上思路前提来想办法。 一、打通网络 让公司的网络能访问到家里电脑的…

什么是 tproxy 透明代理?

在 Istio 最新的 Ambient 模式中&#xff0c;使用了 tproxy 做透明流量劫持&#xff08;见此博客 [1] &#xff09;&#xff0c;这与 Sidecar 模式中基于 IPtables 的流量劫持方式有些许不同&#xff0c;这篇文文章&#xff0c;我们就就一起来探究下什么是 tproxy。 什么是代理…

ChatGPT常用的指令(prompts)系列十——房地产经纪人、物流人员、牙医、网站设计

系列文章目录 内容翻译自&#xff1a;https://github.com/f/awesome-chatgpt-prompts&#xff0c;并加入自己的实践内容 1、 ChatGPT常用的提示语&#xff08;prompts&#xff09;系列一 2、 ChatGPT常用的提示语&#xff08;prompts&#xff09;系列二 3、 ChatGPT常用的提示语…

如果用ChatGpt给OpenTiny官网设计页面会怎样?

听说华为云最近新开源了一个组件库项目,叫OpenTiny。作为一个编程爱好者和对组件库有使用需求的程序猿来讲,必须要看看这个OpenTiny到底有什么不一样,让我立马打开了OpenTiny官网一看究竟。 首先大概了解到OpenTiny 是一套华为云出品的企业级组件库解决方案,适配 PC 端/移…

为什么Facebook账号被封?如何应对Facebook账号被封?

做社媒营销尤其是Facebook&#xff0c;手里有多个账号是家常便饭。运营多个账号您就很可能遇到这一问题&#xff1a;Facebook账号被封。 那么Facebook账号被封该怎么办&#xff1f;本文就聊一聊Facebook账号被封背后的那些事以及如何保护您的Facebook账号。 为什么你的Faceboo…

ChatGPT大封号,注册功能关闭!亚洲成重灾区,网友自救喊话:不要登录,不要登录!...

来源&#xff1a;量子位 | 公众号 QbitAI “不要登录ChatGPT&#xff01;” “暂时远离人工智能和ChatGPT概念板块高位股&#xff01;” 就在这两天&#xff0c;一些关于ChatGPT的疾呼突然在各种社交平台和群聊刷屏了。 而看到这些消息的用户更是感到前所未有的惶恐。 因为导致…

前脚我的 GPT4 被封,后脚收到了文心一言的邀请账号

大家好&#xff0c;我是二哥呀。 一早醒来&#xff0c;我的 ChatGPT Plus 账号就惨遭封禁&#xff0c;很不幸&#xff0c;我刚冲的 Plus 会员&#xff0c;用了不到一周的时间&#xff08;&#x1f62d;&#xff09;。 我没用亚洲的IP&#xff0c;所以网上传的那些不使用亚洲IP…

Twitter账号老被封?一文教会你怎么养号

昨天龙哥给大家科普完要怎么批量注册Twitter账号&#xff0c;立刻有朋友来私信龙哥说里面提到的这个养号和防关联具体是个怎么样的做法。由于Twitter检测机制还是比较敏感的&#xff0c;账号很容易被冻结&#xff0c;所以养号是非常重要的步骤。其实要养好Twitter账号其实并不难…

ChatGPT4 VS ChatGPT3.5:揭秘人工智能语言模型的技术革新

摘要&#xff1a;本文将详细介绍ChatGPT4与ChatGPT3.5之间的关键技术差异&#xff0c;解析为何ChatGPT4在诸多方面超越了ChatGPT3.5&#xff0c;以及这一领域的未来发展趋势。 一、引言 随着人工智能和自然语言处理技术的不断发展&#xff0c;智能对话机器人成为了越来越多人的…