一台服务器可创建多少个TCP连接?

star2017 1年前 ⋅ 1056 阅读

这是一个在面试时经常被问题的问题,实际隐含的是对服务器的优化和创建过多连接时的问题诊断。

生产环境部署应用服务的服务器操作系统基本上是 Linux 服务器,此问题所涉及到更深层的是 Linux 内核 TCP/IP 和 Socket 参数优化。

TCP连接

连接四元组

一个 TCP 连接,系统是通过一个四元组(src_ip,src_port,dst_ip,dis_port)来识别一个连接,即源IP,源端口,目标IP,目标端口。

所以单纯的以一台服务器有 65536 个端口,能承载最大连接数为 65536 个,这个说法是不对的,这里混淆了源端口和目标端口的概念。

TCP连接的服务器机:

Server 通常固定在本地的某个端口上监听,等待 Client 的连接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的情况下,即使 Server 端有多个 IP,本地监听端口也是独占的,因此 Server 端 TCP 连接4元组中只有 remote ip(也就是client ip)和 remote port(客户端port)是可变的,因此:最大 TCP 连接数 = 客户端ip数 x 客户端port数,对于 IPV4,不考虑IP地址分类等因素,最大 TCP 连接数约为 2 的 32 次方(IP数)× 2的16次方(port数),也就是 Server 端单机最大 TCP 连接数约为 2 的 48 次方

理论上单机TCP最大连接数 = 2 的 48 次方 = 281,474,976,710,656,简为 281 万亿的连接。

上面给出的结论都是理论上的单机 TCP 并发连接数,近乎无限制,所以实际的单机并发连接数受硬件资源(内存)、网络资源(带宽)的限制。

一条静止的 TCP 连接(无收发数据)大约需要消耗 3.155 KB 的内存[引];如果有数据发送,需要为每条TCP分配发送缓存区,大小受 net.ipv4.tcp_wmem 参数配置影响,默认情况下最小是 4K。

所以对于企业级的生产型服务器配置,连接数可以达到成千上万,数十万个,一个 8C8G 配置的服务器可以支持百万个连接。若系统优化的好,上限还可以更高。

TCP连接的客户端机:

假如在一台客户机上对服务做压测,则压测客户端会受到端口数限制,因为源IP、目标IP、目标端口不变,但源端口会变,而源端口是在随机分配的端口范围内的。

Linux 端口范围,应用没有绑定的时候随机分配的端口范围:

[root@iZwz92i2oo752l1n1ljw4nZ ~]# cd /proc/sys/net/ipv4/
[root@iZwz92i2oo752l1n1ljw4nZ ipv4]# cat ip_local_port_range 
32768    60999
[root@iZwz92i2oo752l1n1ljw4nZ ~]# sysctl -a|grep ip_local_port_range
net.ipv4.ip_local_port_range = 32768    60999

连接过多

Linux 系统内 一切皆文件,所有设备,进程,连接等等都以文件来描述、访问、管理,需要占用文件描述符。

Linux 下网络服务程序的每一个 TCP 连接都会创建一个 Socket 句柄,即要占一个文件描述符,一旦系统的文件描述符用完,新的连接进来就会返回错误:“Socket/File:Can't open so many files”。这时需要明白是操作系统对打开的文件描述符数量是有限制的。

要提高 TCP 连接数,就要调整文件句柄数量。如果内存、文件描述符足够的话可以创建的连接是没有限制的。

查看内存资源

# cat /proc/meminfo 
# free -m

连接数优化

1. 修改文件句柄数量限制

查看允许 TCP 打开的最大文件句柄数

[root@iZwz92i2oo752l1n1ljw4nZ ~]# ulimit -n
65535

修改文件句柄数,下面是 CentOS 8 为例

[root@iZwz92i2oo752l1n1ljw4nZ ~]# vim /etc/security/limits.conf 

#        - stack - max stack size (KB)
#        - cpu - max CPU time (MIN)
#        - nproc - max number of processes
#        - as - address space limit (KB)
#        - maxlogins - max number of logins for this user
#        - maxsyslogins - max number of logins on the system
#        - priority - the priority to run user process with
#        - locks - max number of file locks the user can hold
#        - sigpending - max number of pending signals
#        - msgqueue - max memory used by POSIX message queues (bytes)
#        - nice - max nice priority allowed to raise to values: [-20, 19]
#        - rtprio - max realtime priority
#
#<domain>      <type>  <item>         <value>
#

#*               soft    core            0
#*               hard    rss             10000
#@student        hard    nproc           20
#@faculty        soft    nproc           20
#@faculty        hard    nproc           50
#ftp             hard    nproc           0
#@student        -       maxlogins       4

# End of file
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535
  • soft nofile:软限制参数,指Linux 系统能够在承受的范围内进一步限制用户同时打开的文件数。
  • hard nofile:硬限制参业数,是根据 Linux 系统服务器硬件的资源情况(主要是内存)计算出来的系统最多能够同时打开的文件数量。

通常 软限制的数值 <= 硬限制的数量。

修改此参数值后,退出当前终端重新登录,不需要重启服务器,就可以看到修改后的最新结果。

2. 调整系统TCP参数

发生方发送数据,接收方接受数据,那么双方必须存在一个保存数据的 Buffer,称为 Socket Buffer,

TCP/IP 的实现都是放在 Kernel 中的,所以 Socket Buffer 也是在 Kernel 中的。Socket Buffer 的大小配置对网络的性能有很大的影响。相关参数如下:

[root@iZwz92i2oo752l1n1ljw4nZ ipv4]# pwd
/proc/sys/net/ipv4
[root@iZwz92i2oo752l1n1ljw4nZ ipv4]# cat tcp_mem 
85122    113498    170244
[root@iZwz92i2oo752l1n1ljw4nZ ipv4]# cat tcp_rmem
4096    87380    6291456
[root@iZwz92i2oo752l1n1ljw4nZ ipv4]# cat tcp_wmem
4096    16384    4194304
  • /proc/sys/net/ipv4/tcp_mem: 系统全局参数,表示所有 TCP 的 Buffer 配置。有三个值,单位为内存页(通常为4K)。

    第一个值,分配给 Tcp 的 Buffer 最小值,page 少于该该值时,Kernel 不会进行干预;

    第二个值,内存使用超过时,kernel 会进入 “memory pressure” 压力模式;

    第三个值,内存使用的上限,超过时会报:Out of socket memory,可能会丢弃报文;

    :最大值根据系统内存大小进行设置;内核分配给 TCP 连接的内存,单位是 Page,1Page = 4KB = 4096 Bytes。查看内核分配给 TCP 连接的内存:

    # getconf PAGESIZE
    4096
    
  • /proc/sys/net/ipv4/tcp_rmen: r 表示 read,也就是 receive,也有三个值。TCP 读取缓存区,单位为Byte字节。

    第一个值,TCP 接收 Buffer 的最少字节数;

    第二个值,TCP 接收 Buffer 的默认值(会被 rmem_default 覆盖);

    第三个值,TCP 接收 Buffer 的最大字节数(会被 rmem_max 覆盖)。

  • /proc/sys/net/ipv4/tcp_wmem: w 表示 write,也就是 send,也有三个值。TCP 发送缓冲区,单位为Byte字节。

    第一个值,TCP 发送 Buffer 的最少字节数;

    第二个值,TCP 发送 Buffer 的默认值(会被 wmem_default 覆盖);

    第三个值,TCP 发送 Buffer 的最大字节数(会被 wmem_max 覆盖)。

系统默认参数:

[root@iZwz92i2oo752l1n1ljw4nZ core]# pwd
/proc/sys/net/core
[root@iZwz92i2oo752l1n1ljw4nZ core]# cat wmem_default 
212992
[root@iZwz92i2oo752l1n1ljw4nZ core]# cat wmem_max 
212992
[root@iZwz92i2oo752l1n1ljw4nZ core]# cat rmem_default 
212992
[root@iZwz92i2oo752l1n1ljw4nZ core]# cat rmem_max 
212992
  • /proc/sys/net/core/wmem_default: TCP数据发送窗口默认字节数。
  • /proc/sys/net/core/wmem_max: TCP数据发送窗口最大字节数。
  • /proc/sys/net/core/rmem_default: TCP数据接收窗口默认字节数。
  • /proc/sys/net/core/rmem_max: TCP数据接收窗口最大字节数。

注意:除了tcp_mem单位为内存页之外,其它几个单位都是字节;而且tcp_mem是全局配置,其它几个都是针对每一个TCP连接的配置参数。

Linux 为了提高系统的吞吐能力,在内核中为 TCP 的发送和接收都做了缓冲队列。为了节省内存,TCP 读取、发送缓冲区最小和默认值都为 4KB。

以上这些参数都是在 /etc/sysctl.conf 文件中定义的,打开此文件会发现,想修改的参数在文件中没有定义,系统给了默认值。此时如果想要修改,则可以直接在文件中添加,然后执行 sysctl -p命令。

参数 默认配置 说明
net.ipv4.tcp_wmem 4096 16384 4194304 TCP 发送缓冲区,单位为字节
net.ipv4.tcp_rmem 4096 87380 6291456 TCP 读取缓冲区,单位为字节
net.ipv4.tcp_mem 85122 113498 170244 TCP 内存大小,单位为页

优化调整参数,通常修改第三个参数,根据物理内存大小,按倍数调整第三个参数的值。

参数值调整并不是越大越好,需要清楚服务器的具体硬件参数配置,并考虑参数调整后对服务器上的其它应用服务的影响。

相关文章

  1. TCP/IP参数详解
  2. 网络编 程实战:性能篇
  3. Linux 中每个 TCP 连接最少占用多少内存?
更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: