在tcp应用中,server事先在某个固定端口监听,client主动发起链接,通过三路握手后创建tcp链接。那么对单机,其最大并发tcp链接数是多少?
如何标识一个TCP链接
在肯定最大链接数以前,先来看看系统如何标识一个tcp链接。系统用一个4四元组来惟一标识一个TCP链接:{local ip, local port,remote ip,remote port}。
client最大tcp链接数
client每次发起tcp链接请求时,除非绑定端口,一般会让系统选取一个空闲的本地端口(local port),该端口是独占的,不能和其余tcp链接共享。tcp端口的数据类型是unsigned short,所以本地端口个数最大只有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(客户端port)是可变的,所以最大tcp链接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp链接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp链接数约为2的48次方。
实际的tcp链接数
上面给出的是理论上的单机最大链接数,在实际环境中,受到机器资源、操做系统等的限制,特别是sever端,其最大并发tcp链接数远不能达到理论上限。在unix/linux下限制链接数的主要因素是内存和容许的文件描述符个数(每一个tcp链接都要占用必定内存,每一个socket就是一个文件描述符),另外1024如下的端口一般为保留端口。在默认2.6内核配置下,通过试验,每一个socket占用内存在15~20k之间。
影响一个socket占用内存的参数包括:
rmem_max
wmem_max
tcp_rmem
tcp_wmem
tcp_mem
grep skbuff /proc/slabinfo
对server端,经过增长内存、修改最大文件描述符个数等参数,单机最大并发TCP链接数超过10万 是没问题的,国外 Urban Airship 公司在产品环境中已作到 50 万并发 。在实际应用中,对大规模网络应用,还须要考虑C10K 问题。
一点常识:
一个网卡对应一个IP地址
一个IP地址对应65535个端口
一个socket(addr, port)能够接受多个socket链接(accept)
一个端口只能被一个socket监听(listen)
曾几什么时候咱们还在寻求网络编程中C10K问题的解决方案,可是如今从硬件和操做系统支持来看单台服务器支持上万并发链接已经没有多少挑战性了。
咱们先假设单台服务器最多只能支持万级并发链接,其实对绝大多数应用来讲已经远远足够了,可是对于一些拥有很大用户基数的互联网公司,每每面临的并发链接数是百万,千万,甚至腾讯的上亿(注:QQ默认用的UDP协议)。虽然如今的集群,分布式技术能够为咱们将并发负载分担在多台服务器上,那咱们只须要扩展出数十台电脑就能够解决问题,可是咱们更但愿能更大的挖掘单台服务器的资源,先努力垂直扩展,再进行水平扩展,这样能够有效的节省服务器相关的开支(硬件资源,机房,运维,电力其实也是一笔不小的开支)。
那么到底一台服务器可以支持多少TCP并发链接呢?
常识一:文件句柄限制
在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多个并发链接。我想有这种错误思路朋友不在少数吧?(其中我过去就一直这么认为)
咱们来分析一下吧
如何标识一个TCP链接:系统用一个4四元组来惟一标识一个TCP链接:{local ip, local port,remote ip,remote port}。好吧,咱们拿出《UNIX网络编程:卷一》第四章中对accept的讲解来看看概念性的东西,第二个参数cliaddr表明了客户端的ip地址和端口号。而咱们做为服务端实际只使用了bind时这一个端口,说明端口号65535并非并发量的限制。
server最大tcp链接数:server一般固定在某个本地端口上监听,等待client的链接请求。不考虑地址重用(unix的SO_REUSEADDR选项)的状况下,即便server端有多个ip,本地监听端口也是独占的,所以server端tcp链接4元组中只有remote ip(也就是client ip)和remote port(客户端port)是可变的,所以最大tcp链接为客户端ip数×客户端port数,对IPV4,不考虑ip地址分类等因素,最大tcp链接数约为2的32次方(ip数)×2的16次方(port数),也就是server端单机最大tcp链接数约为2的48次方。
总结
上面给出的结论都是理论上的单机TCP并发链接数,实际上单机并发链接数确定要受硬件资源(内存)、网络资源(带宽)的限制,至少对咱们的需求如今能够作到数十万级的并发了,你的呢?
这种单台机器10w并发,不考虑内存cpu的实现,主要是程序网络模型的选择。