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

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

生产环境部署应用服务的服务器操作系统基本上是 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 端口范围,应用没有绑定的时候随机分配的端口范围:

1
2
3
4
5
[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 连接数,就要调整文件句柄数量。如果内存、文件描述符足够的话可以创建的连接是没有限制的。

查看内存资源

1
2
# cat /proc/meminfo 
# free -m

连接数优化

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[root@iZwz92i2oo752l1n1ljw4nZ ~]# ulimit -n
65535

#查看 open files 值是默认的能打开的最大文件句柄数
[root@iZf8z5ura2kb73ra6wu0phZ ~]# ulimit -a
core file size (blocks, -c) unlimited
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 6782
max locked memory (kbytes, -l) 16384
max memory size (kbytes, -m) unlimited
open files (-n) 65535
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 6782
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[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 的大小配置对网络的性能有很大的影响。相关参数如下:

1
2
3
4
5
6
7
8
[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 连接的内存:

    1
    2
    # 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 覆盖)。

系统默认参数:

1
2
3
4
5
6
7
8
9
10
[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 连接最少占用多少内存?
作者

光星

发布于

2022-02-01

更新于

2022-06-17

许可协议

评论