Home | 简体中文 | 繁体中文 | 杂文 | Github | 知乎专栏 | 51CTO学院 | CSDN程序员研修院 | OSChina 博客 | 腾讯云社区 | 阿里云栖社区 | Facebook | Linkedin | Youtube | 打赏(Donations) | About
知乎专栏多维度架构

2.18. 多维度架构之Socket连接数

在上一节《多维度架构之会话数》中从运维角度详细介绍了会话数,本章将从开发角度介绍TCP Socket最大连接数。

我先来问几个问题,然后带着问题思考,最后我再逐一解答。

  1. 一台服务器究竟最大能支持多少个网络连接?
  2. 一台服务器能做到百万的连接数吗?
  3. 你想过怎么实现百万的连接吗?

2.18.1. 理解服务器端与客户端

服务器端:是指提供服务的一端,例如 WEB 服务器,服务器通常使用 1 ~ 1024 端口,WEB 服务器是 80 端口,服务器端的端口是固定的。

客户端:是指消费服务的一端,例如浏览器,与服务器80端口建立连接,本地也会消耗一个端口,客户端的端口范围通常是 1025~65535。

有这样一种情况

		
浏览器 —> Nginx —> fastcgi/tomcat —> mysql
		
		

Nginx 本身是服务器,但是同时它也是客户端,同理 fastcgi/tomcat 也是如此。也就是说 Nginx 会消耗掉服务器上的 80端口和1024~65535 之间端口号。

2.18.2. 影响连接的因素有哪些?

上面解释了服务器端与客户端,服务器能开出的端口数量会影响最终连接数的数量。除此之外还有哪些因素呢?

文件打开数量,还以WEB服务器为例,浏览器请求HTML资源,Nginx 会到磁盘上索引对应的文件并打开,将文件内容读到内存,并返回给浏览器。如果系统限制了文件打开数量,Socket 请求仍会失败。如果是 Unix Socket 文件打开数量限制,直接影响 Socket 连接数。

磁盘IO性能,多线程打开文件太多,导致读取问题等待时间过长,造成线程堆积。

内存限制,服务器端每接受一个TCP连接请求,就会为多线程/进程分配内存空间。如果限制了进城的内存空间,内存不足,线程创建失败。也就是意味着无法再有新链接进入服务器。

进程数限制,这个因素只影响机遇多进程的TCP Socket,对于多线程TCP Socket 不影响。

网卡的带宽,每个TCP 链接请求产生多少带宽,全负荷工作时带宽开销时多少,一般网卡时1GB,如果超过1GB,外面的链接也是会超时的。目前光纤网卡主流40GB 性价比比较高。

网络设备,交换机容量和背板带宽,从客户端到服务器端,需要经过交换机,交换机的交换能力,和背板带宽(交换机内存)决定了你从客户能发出多少链接,服务器端能接受多少链接。交换机不给力,并发就上不去。还有路由器或防火墙的会话数,这部分请参看《多维度架构之会话数》

以上设置通过 ulimit / sysctl 两个命令完成内核参数的调整。这里不多介绍,有兴趣看笔者相关文章,如果比较懒可以到我的知乎主页,点付费咨询。

2.18.3. 程序怎么写?

直接进入主题,服务器内核参数调整完毕,网络设备调试完成,一切就绪,程序改怎么写才能达到百万级TCP链接呢?

不知你是否注意到 nginx 有一个 listen 配置项,Redis 里有一个 bind 配置项。很多人可能都不理解时用来干什么的。

它是用来配置使用那个IP地址监听80端口,它不仅仅用来干这个。当配置为127.0.0.1 的时候不走网卡,不受网卡带宽的限制,所以在同一台服务器的Socket调用,我们通常使用localhost。当配置为 0.0.0.0 的时候表示监听所有IP地址,可以是多个网卡提高整体带宽。

我们仅仅是用来测试,所以这个程序应该尽量不操作磁盘,不去打开文件,减少内存不必要的开销,节省网卡带宽。

对于客户端内核端口范围配置作用于单个IP地址,所以为了能够使用足够多的本地端口,我们可以在服务器上配置多个IP地址,通常一个网卡可以配置 254个IP地址。

得出 (65535 - 1024)* 254 = 理论能开出的端口

还没完,我们上网的出口是走默认网关那个网卡的默认IP地址,Linux eth0 上配置的IP地址,而你设置了另外254个IP地址是 eth0:1~254 或者分布到其他网卡上(eth1,eth2……)。你测试会发现,对于服务器来说访问过来的IP地址永远都是 eth0 那个IP地址,也无法突破 65535的限制。如果你想使用其他的IP地址发起请求,需要额外的配置,修改路由表。

好了,到此为止原理已经将完,你可以试试写一个百万链接的服务器端试试。