可能做网络相关开发的你知道一个server上一个ip 最多只能使用65535个,为什么是65535因为linux下,这里如果还要减去系统保留的那就更少了,至于系统保留多少,可以通过以下配置进行配置:
/proc/sys/net/ipv4/ip_local_port_range
或者是通过sysctl进行永久配置。
linux下标识一个连接是通过四元组标识的即:「源ip,源端口;目标ip,目标端口」,所以对于一台只有一个ip的客户机和服务端能建立的连接是可以计算出来的。
所以如果你要对你写的服务是否能够支撑100万长连接,如果按照60000(这里只考虑一台服务器只有一个ip可用(感谢条友提醒,特意备注下以免大家误解)一台客户机服务器来算,那么需要17台服务器。(这里假设每个客户机上都是一个网卡)那么我们有有没有更好的办法来测试100万长连接,而不需要17个客户端服务器。
用17个客户端服务器来建立100万长连接肯定是可行的,但是浪费资源,增加部署工作负担。
下面简单介绍下一些可行以及不可行的方案如何基于1台服务端服务器、一台客户端服务器建立100万长连接:
1. 服务端服务器添加多个虚拟网卡,绑定不同的ip,然后让服务端程序监听在不同的ip上监听不同的端口。但是服务器端的端口最多也只能使用65535个。这个我没有尝试过,理论上是不可行的,大家可以试下然后告诉我~【不可行】
2.客户端服务器添加多个虚拟网卡,比如20个,分别绑定不同的ip,最终也没法逃过65535个端口的约束【不可行】
3. 使用SO_REUSEPORT 特性,这是google 提交的一个linux 补丁。该补丁做什么工作呢?
它支持多个进程或者线程绑定到同一端口,提高服务器程序的性能。这里的绑定是bind,可以是客户端、也可以是服务端。linux内核(>= 3.9)支持SO_REUSEPORT特性。
所以我们可以利用该补丁来建立100万连接。
1)首先服务端程序需要监听17个端口,可以是一个ip
2)其次在客户端侧便利本地可用的端口范围,每个port 需要跟服务端的17个端口进行建立连接。
每个端口第一次连接调用connect 时需要把对应的socket 设置SO_REUSEPORT开关打开,然后在该socket上指定本地端口(用bind来绑定即可)。然后用同样的方法对服务端第一个端口调用connect,依次类推,只要客户机上内存足够,100万长连接完全是没有问题的。
int sfd = socket(domain, socktype, 0); int optval = 1; setsockopt(sfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval)); bind(sfd, (struct sockaddr *) &addr, addrlen);当然这种测试方法对于要求测试高并发的请求量是,有一定的局限性的。
管理SO_REUSEPORT特性还可以用来解决,服务端多worker 监听模型中的惊群效应。

Fig 1 多worker监听模型
关于SO_REUSEPORT 原理请参考:https://lwn.net/Articles/542629/
















