"扩展 Linux ephemeral 端口限制"

默认情况下,单一Linux能发起的客户端连接数是十分有限的,为此,我们要测试大规模连接程序时不得不启动很多客户端机器模拟连接。下面介绍一些增加单台Linux发起连接数的方法。

增加文件打开数

第一步最为基础的,提高打开文件描述符的数量。默认的情况下,这个配置为1024,是不能满足我们的使用的。增加到999999个:

$ sudo ulimit -n 999999

持久化这个配置,可以在/etc/security/(或/etc/security.d/,取决于你的发行版)下建立文件,增加

*       hard    nofile      999999
*       soft    nofile      999999

这将对所有用户起效。

增加客户端端口数

当Linux发起客户端连接时,如果没有显式指定,会给客户端socket绑定一个 ephemeral 端口。这个端口的范围是从这个区间选取的:

 $ cat /proc/sys/net/ipv4/ip_local_port_range
32768   61000

如果这个区间的端口耗尽,socket就会产生cannot assign requested address的错误。要增加端口范围,我们需要把他设置得更大:

$ sudo echo "1025 65535" > /proc/sys/net/ipv4/ip_local_port_range

这样,单台机器就可以发出六万多个连接。

增加虚拟网卡

对于内存大一点的客户端机器,六万多个连接远不是其性能极限。由于IP消息中,一条消息是由 src_addr, src_port, dst_addr, dst_port 四元组标识,所以要增加连接,我们需要更多IP。在Linux上,我们可以启动虚拟网卡绑定额外的IP。

$ sudo ifconfig eth0:0 192.168.1.100
$ sudo ifconfig eth0:1 192.168.1.101
...

要关闭这些虚拟网卡

$ sudo ifconfig eth0:0 down

使用虚拟网卡连接

拥有多个IP之后,客户端socket需要显示绑定这些IP才行,以python为例,在connect前调用:

sock.bind((local_addr, local_port))

可以指定连接的源地址和端口。在普通的Linux编程里,当你指定local_port0时,Linux会分配一个之前提到的 ephemeral 端口。但是当使用虚拟IP时,如果仍然指定0,系统并不会因为IP不同而重用端口号,达到六万多的限制后,仍然会抛出不能获得地址的异常。

实际上是可以获得的,这里需要用户显式地指定端口好。如果需要大规模的连接,那就一个一个绑定好了。

启用time_wait reuse和recycle

Linux的socket进入time_wait后需要有一定的时间回收,之后端口才能重新使用。这在大规模测试的时候就比较麻烦,为了免去等待,可以打开tw_reusetw_recycle这两个选项。

$ echo 1 > /proc/sys/net/ipv4/tcp_tw_recycle
$ echo 1 > /proc/sys/net/ipv4/tcp_tw_reuse

注意这两个选项都比较激进,最好仅在测试机上使用。