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

Posted PHP饭米粒

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漫画 | 一台Linux服务器最多能支撑多少个TCP连接?相关的知识,希望对你有一定的参考价值。

困惑很多人的并发问题

在网络开发中,我发现有很多同学对一个基础问题始终是没有彻底搞明白。那就是一台服务器最大究竟能支持多少个网络连接?我想我有必要单独发一篇文章来好好说一下这个问题。

很多同学看到这个问题的第一反应是65535。原因是:“听说端口号最多有65535个,那长连接就最多保持65535个了”。是这样的吗?还有的人说:“应该受TCP连接里四元组的空间大小限制,算起来是200多万亿个!”

如果你对这个问题也是理解的不够彻底,那么今天讲个故事讲给你听!

一次关于服务器端并发的聊天

"TCP连接四元组是源IP地址、源端口、目的IP地址和目的端口。任意一个元素发生了改变,那么就代表的是一条完全不同的连接了。拿我的nginx举例,它的端口是固定使用80。另外我的IP也是固定的,这样目的IP地址、目的端口都是固定的。剩下源IP地址、源端口是可变的。所以理论上我的Nginx上最多可以建立2的32次方(ip数)×2的16次方(port数)个连接。这是两百多万亿的一个大数字!!"

"进程每打开一个文件(linux下一切皆文件,包括socket),都会消耗一定的内存资源。如果有不怀好心的人启动一个进程来无限的创建和打开新的文件,会让服务器崩溃。所以linux系统出于安全角度的考虑,在多个位置都限制了可打开的文件描述符的数量,包括系统级、用户级、进程级。这三个限制的含义和修改方式如下:"

  • 系统级:当前系统可打开的最大数量,通过fs.file-max参数可修改
  • 用户级:指定用户可打开的最大数量,修改/etc/security/limits.conf
  • 进程级:单个进程可打开的最大数量,通过fs.nr_open参数可修改
  • "我的接收缓存区大小是可以配置的,通过sysctl命令就可以查看。"

    $ sysctl -a | grep rmem
    net.ipv4.tcp_rmem = 4096 87380 8388608
    net.core.rmem_default = 212992
    net.core.rmem_max = 8388608

    "其中在tcp_rmem"中的第一个值是为你们的TCP连接所需分配的最少字节数。该值默认是4K,最大的话8MB之多。也就是说你们有数据发送的时候我需要至少为对应的socket再分配4K内存,甚至可能更大。"

    "TCP分配发送缓存区的大小受参数net.ipv4.tcp_wmem配置影响。"

    $ sysctl -a | grep wmem
    net.ipv4.tcp_wmem = 4096 65536 8388608
    net.core.wmem_default = 212992
    net.core.wmem_max = 8388608

    "在net.ipv4.tcp_wmem"中的第一个值是发送缓存区的最小值,默认也是4K。当然了如果数据很大的话,该缓存区实际分配的也会比默认值大。"


    服务端百万连接达成记

    “准备啥呢,还记得前说过Linux对最大文件对象数量有限制,所以要想完成这个实验,得在用户级、系统级、进程级等位置把这个上限加大。我们实验目的是100W,这里都设置成110W,这个很重要!因为得保证做实验的时候其它基础命令例如ps,vi等是可用的。

    活动连接数量确实达到了100W:

    $ ss -n | grep ESTAB | wc -l  
    1000024

    当前机器内存总共是3.9GB,其中内核Slab占用了3.2GB之多。MemFree和Buffers加起来也只剩下100多MB了:

    $ cat /proc/meminfo
    MemTotal:        3922956 kB
    MemFree:           96652 kB
    MemAvailable:       6448 kB
    Buffers:           44396 kB
    ......
    Slab:          3241244KB kB

    通过slabtop命令可以查看到densty、flip、sock_inode_cache、TCP四个内核对象都分别有100W个:


    结语

    互联网后端的业务特点之一就是高并发. 但是一台服务器最大究竟能支持多少个TCP连接,这个问题似乎却又在困惑着很多同学。希望今天过后,你能够将这个问题踩在脚下摩擦!

    学习是一件痛苦的事情,尤其咱们号里很多读者朋友都是工作满一天了再来看我的技术号的文章的。我一直都在琢磨到底怎么样组织技术内容形式,能让大家理解起来更能省一点脑细胞呢。这篇服务器的最大并发数的文章是早就想发的,但是写了两三个版本都不满意。今天终于想出了一种让大家更容易理解的方式,算过了自己这关了。

    如果您喜欢我的文章、并觉得它有用,期望您能不吝把它转发到你的朋友圈,技术群。或者哪怕是点个赞,点个再看都可以。触达更多的技术同学并收获大家的反馈将极大地提升彦飞的创作动力!

    改天再讲客户端,敬请期待!!


    ----------线-----------


    PHP(phpfamily) PHPer




    稿稿


    稿


    shenzhe163@gmail.com


      张彦飞allen    

    一台Linux机器上最多能建立多少个TCP连接?

    一台Linux机器上最多能建立多少个TCP连接?

    看面经看到有的公司面试会问这个问题,上网搜了搜感觉没有找到特别全面且易懂的答案,遂思考后总结如下,如有纰漏还请指出!

    受限制的因素:

    1. 计算机(或虚拟机)能够打开的最大文件个数 file-max,受硬件配置影响;

    在通信的每一方(Linux OS)上,每个socket其实都属于一个打开的文件,通过文件描述符fd作为句柄去操作,该限制可以用ulimit -a查看,也可以用cat /proc/sys/fs/file-max查看,open file标识了当前用户下进程默认最多能打开的文件描述符个数,缺省为1024。


    可以通过修改配置文件的方式修改该上限值:sudo vi /etc/security/limits.conf
    在文件尾部写入以下配置,soft 软限制,hard 硬限制。如下所示:

    soft nofile 65536		#这里将软限制改为65536,简单的匹配0~65535端口号per Port per Connnection的情况。
    hard nofile 100000
    

    说到这里有不得不涉及进程的因素:
    在linux上进行网络编程,若需要打开一个文件并获取其文件描述符,必然基于一个进程,进程的地址空间内部存有打开文件描述符列表,简称fd列表,那么我们的机器上有几个个关于进程的参数是matter的:

    • 系统分配给一个进程的空间是多大
    • 一个进程最多能打开多少个fd
    • 系统最多能用多少个进程

    因为进程的启用会分配除了fd列表之外的其他资源,这些资源都会占用cpu和内存,按照这样的逻辑,在一台Linux机器上最多能建立多少个TCP连接?的命题下,进程越少,每个进程能打开的文件描述符越多越好,因为这样资源的有效率更高。

    有的同学也可能想过用线程去开fd,但是需要注意的是,即使线程在其独立的执行栈中使用open()打开了某个文件,并用int变量去接收了操作句柄,这并不代表其他线程就不能调用到这个fd了,因为最终fd是放置在同一进程的fd列表上的,线程栈内部私有的只是一个变量,并不是fd的绝对控制权。我们也知道开启线程也需要为线程分配独立的执行栈,那么用线程去打开fd反而会额外占用更多的“无效资源”。

    1. 最大端口数ip_local_port_range

    TCP数据包中用于表述端口的字段是16位,最多可以表示2^16也就是65535个端口;

    使用sysctl net.ipv4.ip_local_port_rangecat /proc/sys/net/ipv4/ip_local_port_range,一般情形下:linux临时端口号范围是(32768,61000)

    1. ip数量

    ip(ipv4)数量的理论最大值,受限于ip的位数 ---- ip长度为32位,那么极限最优条件下(但没有这个可能)单机可以拥有2^32个ip地址,但这样就把世界上所有的ip都用光了。

    每个TCP连接由唯一的TCP四元组可以唯一确定,即:(local IP, local Port, remote IP, remote Port)

    那么最理想情况下,单机可以承受的最大TCP连接量为:

    2^32(local IP) x 2^16(local Port) x 2^32(remote IP) x 2^16(remote Port)

    但是就目前的TCP协议来说,显然这是不可能的,首先,不会有一台机器可以占用所有的ip,其次需要考虑机器是否能正常的打开2^16个端口,以及机器是否支持那么多的打开文件,最最最重要的是,机器能否有那么大的内存和CPU资源来维护这些TCP连接。

    1. 内存

    因为Linux每维护一条TCP连接都要花费资源。处理连接请求,保活,数据的收发,以及TCP保证可靠传输的各种机制都需要消耗CPU资源,维持TCP连接主要消耗内存。

    我们题目的问题是考虑最大多少个连接,所以我们先不考虑数据的收发。

    那么TCP在静止的状态下,就不怎么消耗CPU了(先不考虑心跳包保活的问题),主要消耗内存。而Linux上内存是有限的。

    一条TCP连接如果不发送数据的话,消耗内存是3.3K左右。

    如果有数据发送,需要为每条TCP分配发送缓存区,大小受参数net.ipv4.tcp_wmem配置影响,默认情况下最小是4K

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

    对于提供单一服务的具体的服务器来说,不考虑端口复用(unix/linux的SO_REUSEADDR选项)的情况下,例如对于一台Nginx Server,它的IP和端口是固定的。tcp连接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的。它理论上可能建立的最大的连接数是2的32次方(ip数)×2的16次方(port数),大约两百万亿!

    Linux上除了监听80以外,还可以监听其它的端口,例如Mysql的3306, Redis的6339,当然条件允许的话所有65535个端口你都可以用来监听一遍。

    以上是关于漫画 | 一台Linux服务器最多能支撑多少个TCP连接?的主要内容,如果未能解决你的问题,请参考以下文章

    一台Linux机器上最多能建立多少个TCP连接?

    一台Linux机器上最多能建立多少个TCP连接?

    zookeeper一台机器上最多能启动多少个ZooKeeper客户端

    linux一个文件夹内最多能放多少文件

    最多能创建多少个 TCP 连接?

    最多能创建多少个 TCP 连接?