keep live c100w - yaokun123/php-wiki GitHub Wiki

如何做到单机百万长连接

一、too many open files问题解决

linux下一切皆文件,包括socket

1、ulimit -n 单个用户能打开的文件上线

1、ulimit -n:查看当前设置。
2、ulimit -n 1000000:进行临时性设置。
3、要想永久生效,你可以修改/etc/security/limits.conf文件,增加下面的行:
*         hard    nofile      1000000
*         soft    nofile      1000000
root      hard    nofile      1000000
root      soft    nofile      1000000

hard limit不能大于/proc/sys/fs/nr_open,因此有时你也需要修改nr_open的值

2、fs.nr_open 单个进程上可打开的文件数

1、临时性设置:执行echo 2000000 > /proc/sys/fs/nr_open
2、永久设置:修改/etc/sysctl.conf文件,增加fs.nr_open = 2000000

3、fs.file-max 整个系统上可打开的最大文件数

1、临时性设置:echo 1000000 > /proc/sys/fs/file-max
2、永久设置:修改/etc/sysctl.conf文件,增加fs.file-max = 1000000

4、查看当前系统使用的打开文件描述符数,可以使用下面的命令:

cat /proc/sys/fs/file-nr

10208	0	1582530

其中第一个数表示当前系统已分配使用的打开文件描述符数
第二个数为分配后已释放的(目前已不再使用)
第三个数等于file-max。

二、Cannot assign requested address问题解决

端口号限制
sysctl -a|grep net.ipv4.ip_local_port_range

net.ipv4.ip_local_port_range = 32768	61000

端口范围:61000 - 32768 = 28232

sudo sysctl -w net.ipv4.ip_local_port_range="1025 61000"

三、Connect耗时越来越大,怎么解决?

1、临时端口分配策略

/proc/sys/net/ipv4/ip_local_port_range文件指定了临时端口号的下界low和上界high,默认情况下,low是偶数,在我的电脑上low和hight的值分别是32768和61000

  • 优先给bind(分配随机的与low奇偶性不同的端口,也就是奇数端口。如果奇数端口号分配完了,才会尝试分配偶数端口。

  • 优先给connect分配与low奇偶性相同的临时端口,也就是偶数端口。如果偶数端口号分配完了,才去尝试分配奇数端口。

2、connect性能衰减的原因

  • 获取port range中设置的端口范围,将端口资源按照偶数、奇数分为两组,依次尝试去获取,每次获取的起点是随机的。

  • 当我们完全占用偶数组的端口后,所有后续的connect调用,所需的源端口应该位于奇数组中,然而该函数依旧会尝试完整遍历偶数组资源。

3、高版本 Linux 协议栈源端口选择性能急剧衰减问题

自kernel 4.2开始,端口资源的分配策略改了

https://blog.lucode.net/network-stack/problem-of-performance-degrading-in-linux-src-port-selecting.html

4、解决方式 由于是linux内核随机选择端口的问题,无法有效解决这个问题,临时解决方式就是人为指定端口。

四、虚拟IP

每台机器的临时端口数量会有限制,那么单台机器怎么能发送百万长连接呢?可以使用多台机器、虚拟机、虚拟IP等方式来解决。

ifconfig enp0s31f6:0 192.168.31.10 netmask255.255.224.0 up

enp0s31f6:0:表示这个VIP绑定的多目标网卡
192.168.31.10:这个虚拟IP
up:表示启用这个VIP

创建多个虚拟IP的脚本

#!/bin/bash
NETMASK="255.255.224.0"
IFS=$'\n' IPS=($(cat ip.txt))

for i in "${!IPS[@]}";do
    echo ifconfig enp0s31f6:$i ${IPS[$i]} netmask $NETMASK up
    ifconfig enp0s31f6:$i ${IPS[$i]} netmask $NETMASK up
done

ip.txt

192.168.31.10
192.168.31.11
192.168.31.12
......

五、Linux中每个TCP连接最少占用多少内存

(3605592KB-355880kB)/1000/1000 = 3.25KB