问题
服务器进程会有一个最大连接数,如果达到最大连接数,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是用户使用的。对于有一个机器,如果只有一个IP地址,并且连接全部作为client,由于每个TCP连接都要占一个端口号,所以最多可以有60000多个并发连接。
#参考
详解Linux服务器最大tcp连接数
http://www.cnblogs.com/fjping0606/p/4729389.html