用Netty实现单机百万TCP长连接

一、模拟单机连接瓶颈
我们知道,通常启动一个服务端会绑定一个端口,例如8000端口,当然客户端连接端口是有限制的,除去最大端口65535和默认的1024端口及以下的端口,就只剩下1024~65535个,再扣除一些常用端口,实际可用端口只有6万个左右。

那么,我们如何实现单机百万连接呢?假设在服务端启动[8000,8100]这100个端口,100×6万就可以实现600万左右的连接,这是TCP的一个基础知识,虽然对于客户端来说是同一个端口号,但是对于服务端来说是不同的端口号,由于TCP是一个私源组概念,也就是说它是由源IP地址、源端口号、目的IP地址和目的端口号确定的,当源IP地址和源端口号是一样的,但是目的端口号不一样,那么最终系统底层会把它当作两条TCP连接来处理,所以这里取巧给服务端开启了100个端口号,这就是单机百万连接的准备工作,如下图所示。

单机1024及以下的端口只能给ROOT保留使用,客户端端口范围为1025~65535,接下来用代码实现单机百万连接的模拟场景。先看服务端类,循环开启[8000-8100)这100个监听端口,等待客户端连接。下面已Netty为例编写代码如下。

案例见:springboot-netty-demo

二、服务器和客户端配置
1. 修改server配置
1.1 突破局部文件句柄的限制
首先在服务端输入命令,看一下单个进程所能支持的最大句柄数。

$ ulimit -n

输入命令后,会出现1024的数字,表示Linux系统中一个进程能够打开的最大文件数,由于开启一个TCP连接就会在Linux系统中对应创建一个文件,所以就是受这个文件的最大文件数限制。
那为什么前面演示的服务端连接数最终定格在870,比1 024小呢?其实是因为除了连接数,还有JVM打开的文件Class类也算作进程内打开的文件,所以,1 024减去JVM打开的文件数剩下的就是TCP所能支持的连接数。接下来想办法突破这个限制,首先在服务器命令行输入以下命令,打开/etc/security/limits.conf文件。

$ vim /etc/security/limits.conf

然后在这个文件末尾加上下面两行代码。

* hard nofile 1000000
* soft nofile 1000000

前面的*表示当前用户,hard和soft分别表示限制和警告限制,nofile表示最大的文件数标识,后面的数字1000 000表示任何用户都能打开100万个文件,这也是操作系统所能支持的最大值,如下图所示。

接下来,输入以下命令。

$ ulimit -n

这时候,我们发现还是1 024,没变,重启服务器。将服务端程序和客户端程序分别重新运行,这时候只需静静地观察连接数的变化,最终连接数停留在137 920,同时抛出了异常,如下所示。

1.2 突破全局文件句柄限制
首先在Linux命令行输入以下命令,可以查看Linux系统所有用户进程所能打开的文件数。

$ cat /proc/sys/fs/file-max
3210650

$ vim /etc/sysctl.conf
fs.file-max=1000000

重启Linux服务器

$ cat /proc/sys/fs/file-max
1000000

2. 修改客户机设置

cat /proc/sys/net/ipv4/ip_local_port_range
值为32768 61000

大概也就是共61000-32768=28232个端可用,单个IP对外只能发送28232个TCP请求。
以管理员身份,把端口的范围区间增到最大

echo "1024 65535"> /proc/sys/net/ipv4/ip_local_port_range

现在有64511个端口可用.

以上做法只是临时,系统下次重启,会还原。 需要做永久修改, vi /etc/sysctl.conf文件,增加一行内容

net.ipv4.ip_local_port_range= 1024 65535
sysctl -p

 

posted on 2023-01-14 17:07  Ruthless  阅读(2208)  评论(1编辑  收藏  举报