问题

服务器进程会有一个最大连接数,如果达到最大连接数,server端报错:

listener accept fail: accept tcp [::]:6080: accept4: too many open files

此时,client端报错:

dial tcp 172.20.152.87:6080: i/o timeout

client连接超时

下面来看下哪些因素影响最大连接数。

最大连接

如何标识一个TCP连接

在确定最大连接数之前,先来看看系统如何标识一个tcp连接。系统用一个4元组来唯一标识一个TCP连接:{local ip, local port,remote
ip,remote port}。

client最大tcp连接数

client每次发起tcp连接请求时,除非绑定端口,通常会让系统选取一个空闲的本地端口(local
port),该端口是独占的,不能和其他tcp连接共享。tcp端口的数据类型是unsigned
short(2字节),因此本地端口个数最大只有65536,端口0有特殊含义,不能使用,这样可用端口最多只有65535,所以在全部作为client端的情况下,最大tcp连接数为65535,这些连接可以连到不同的server
ip。

server最大tcp连接数


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

上面给出的是理论上的单机最大连接数,在实际环境中,受到机器资源、操作系统等的限制,特别是sever端,其最大并发tcp连接数远不能达到理论上限。


在unix/linux下限制连接数的主要因素是内存和允许的文件描述符个数(每个tcp连接都要占用一定内存,每个socket就是一个文件描述符),在默认2.6内核配置下,经过试验,每个socket占用内存在15~20k之间。

下面针对两个主要限制:文件句柄限制和端口限制进行说明。

文件句柄限制

在linux下每一个tcp连接都要占一个文件描述符,如果达到上限,就会出现错误:“Socket/File:Can’t open so many files”。

操作系统对可以打开的最大文件数有限制。

文件句柄进程级限制

执行 ulimit -n 输出 1024,说明对于一个进程而言最多只能打开1024个文件,所以你要采用此默认配置最多也就可以并发上千个TCP连接。

*
临时修改
ulimit -n 1000000,但是这种临时修改只对当前登录用户目前的使用环境有效,系统重启或用户退出后就会失效。

*
重启后失效的修改(不过我在CentOS 6.5下测试,重启后未发现失效)
编辑 /etc/security/limits.conf 文件, 修改后内容为

* soft nofile 1000000

* hard nofile 1000000
*
永久修改

编辑/etc/rc.local,在其后添加如下内容

ulimit -SHn 1000000

文件句柄全局限制

执行 cat /proc/sys/fs/file-nr
输出 9344 0 592026
分别为:
1.已经分配的文件句柄数,
2.已经分配但没有使用的文件句柄数,
3.最大文件句柄数。

但在kernel 2.6版本中第二项的值总为0,这并不是一个错误,它实际上意味着已经分配的文件描述符无一浪费的都已经被使用了 。

我们可以把这个数值改大些,用 root 权限修改 /etc/sysctl.conf 文件:

fs.file-max = 1000000
net.ipv4.ip_conntrack_max = 1000000
net.ipv4.netfilter.ip_conntrack_max = 1000000

端口号范围限制

操作系统上端口号1024以下是系统保留的,从1024-65535是用户使用的。由于每个TCP连接都要占一个端口号,所以最多可以有60000多个并发连接。

参考

详解Linux服务器最大tcp连接数
http://www.cnblogs.com/fjping0606/p/4729389.html
<http://www.cnblogs.com/fjping0606/p/4729389.html>