应读者要求,今天分享单机百万 TCP 连接测试源码
应读者要求,今天分享单机百万 TCP 连接测试源码
原创张彦飞allen开发内功修炼2021-02-18 19:08
收录于话题#开发内功修炼之网络篇30个
点击上方蓝字”开发内功修炼“,关注并设为星标
飞哥的硬核文章将第一时间送达~~~
在看完服务器、客户端的两篇单机达成百万 TCP 连接的文章以后,有很多同学反馈也想实际动手做做实验,感受一下。为了方便大家,我今天就把我实验时使用的源代码整理了出来。
测试百万连接我用到的方法有两种:
- 第一种是服务器端只开启一个进程,然后使用很多个客户端 ip 来连接
- 第二种是服务器开启多个进程,这样客户端就可以只使用一个 ip 即可
咱们今天先来看第一种方法,另一种下次再发。源码地址如下,需要手工复制~
源码地址: https://github.com/yanfeizhang/coder-kung-fu/tree/main/tests/network/test01
鉴于整个实验做起来还是有点小复杂,所以还是单独写一篇文章,配合源代码一起,让大家动手起来更轻松。
一、服务器准备
1.1 最大可打开文件句柄调整
细节不说了,直接给出最佳调整办法。如果踩了坑,或者想了解更详细的内容,请参见下文
《刨根问底儿,看我如何处理 Too many open files 错误!》
先加大系统级最大句柄数 fs.file-max 为大于 100 万,注意要多打一点余量,干脆直接设置成 110 万。另外同时要修改的还有系统进程级参数 fs.nr_open, 也一起改成 110 万。
```plain text #vi /etc/sysctl.conf fs.file-max=1100000 fs.nr_open=1100000
1
2
3
4
5
6
7
8
sysctl -p 使得设置生效。并使用 sysctl -a 验证是否真正生效
```plain text
#sysctl -p
#sysctl -a
fs.file-max = 1100000
fs.nr_open = 1100000
接着再加大用户进程的最大可打开文件数量限制(nofile),这个是在 /etc/security/limits.conf 中配置。这两个是用户进程级的,可以按不同的用户来区分配置。这里为了简单,就直接配置成所有用户 * 了。
```plain text
vi /etc/security/limits.conf
- soft nofile 1010000
- hard nofile 1010000 ```
注意 hard nofile 一定要比 fs.nr_open 要小,否则可能导致用户无法登陆。
配置完后,开个新控制台即可。使用 ulimit 命令校验生效
```plain text #ulimit -n 1010000
1
2
3
4
5
6
7
**1.2 启动 server 开始监听**
启动 server
```plain text
php server.php 0.0.0.0 8090
使用 netstat 命令确保 server 监听成功。
```plain text netstat -nlt | grep 8090 tcp 0 0.0.0.0:8090 0.0.0.0:* LISTEN
1
2
3
4
5
6
7
8
9
10
## 二、客户端准备
**2.1 调整可用端口范围**
默认情况下,Linux 只开启了 3 万多个可用端口。但我们今天的实验里,一个进程要达到 5 万的并发。所以,端口范围的内核参数也是需要修改的。
```plain text
#vi /etc/sysctl.conf
net.ipv4.ip_local_port_range = 5000 65000
执行 sysctl -p 使之生效。
2.2 加大最大可打开文件数
和服务端对应,客户端的 fs.file-max 也需要加大到 110 万。不过进程级的参数 fs.nr_open 设置到 60000 就够了。
```plain text #vi /etc/sysctl.conf fs.file-max=1100000 fs.nr_open=60000
1
2
3
4
5
6
7
8
sysctl -p 使得设置生效。并使用 sysctl -a 查看是否真正生效
```plain text
#sysctl -p
#sysctl -a
fs.file-max = 1100000
fs.nr_open = 60000
接着再加大用户进程的最大可打开文件数量限制(nofile),和服务器中的配置方法一样。不过由于客户端我们是要开 20 个进程来测的,所以每个进程最大开到 5 万个文件数就够了。同样预留一点余地,所以设置成 55000。
```plain text
vi /etc/security/limits.conf
- soft nofile 55000
- hard nofile 55000 ```
配置完后,开个新控制台即可。使用 ulimit 命令校验生效
```plain text #ulimit -n 55000
1
2
3
4
5
6
7
8
9
10
11
**2.3 挑选客户端可用的新 ip**
因为我们这次是要用单台客户端来连接同一个 server 的同一个端口。而单客户端 ip 所能达到的最高连接数是受端口数量限制。最多只有 65535 - 1024 = 64k 个。
解决办法之一就是使用 20 台客户端,每个客户端发起 5 万个连接同时来连接这一个server。通过这样让服务器能达到 100 万条 TCP 并发。 但是这个方法实际操作起来太困难了,所以不可行。
另外一个办法就是采用为一台机器,在这个机器上配置多个 ip 的方式来搞。在 linux 上可以使用 ifconfig 命令为一台机器配置多个 ip。例如你的 linux 上的网卡设备为 eth0,现在想配置一个别名为 eth0:1,ip 为 CIP1,掩码为 255.255.248.0 。则配置 ip 的命令如下:
```plain text
ifconfig eth0:1 CIP1 netmask 255.255.248.0 up
所以接下来的事情就是在你的网络环境中寻找 20 个可用的 ip。假设可用的ip分别是 CIP1,CIP2,……,CIP20。
注意:配置的 ip 必须不能和局域网的其它机器冲突,否则会影响这些机器的正常网络包的收发。
2.4 为客户端配置新的 ip
确定了 ip 以后,则开始动手修改测试源码 clientd.php 中的 $ips 数组,子网掩码。
为了确保局域网内没有这些 ip,需要先执行代码中提供的一个小工具来验证一下
```plain text php clientd.php ping
1
2
3
4
5
6
7
当所有的 ip 的 ping 结果均为 false 时,方可进行下一步实验。
配置所有 ip 并启动网卡。
```plain text
php clientd.php ifup
使用 ifconfig 命令查看 ip 是否配置成功。
```plain text #ifconfig eth0 eth0:0 eth0:1 … eth:19
1
2
3
4
5
6
7
8
9
ip 配置完成后,就可以进行下一步实验了。
## 三、开始连接实验
修改 clientd.php 中的服务器 ip 和端口。然后开始连接
```plain text
php clientd.php start
同时,另启一个控制台。使用 watch 命令来实时观测 ESTABLISH 状态连接的数量。
当然,实验过程中不会一帆风顺,可能会有各种意外情况发生。遇到问题别慌,根据错误提示看下是哪里不对。然后调整一下,重新做就是了。
重做的时候需要重启客户端和服务器。对于客户端,杀掉所有的客户端进程的方式是
```plain text php clientd.php stop
1
2
3
4
5
6
7
8
对于服务器来说,就更简单了,直接 ctrl + c 终止服务器进程,再重新启动就行了。如果发现端口被占用,那是因为操作系统还没有回收,等一会儿再启动 server 就行。
当你发现连接数量超过 100 万的时候,你的实验就成功了。
```plain text
watch "ss -ant | grep ESTABLISH"
1000013
这个时候别忘了查看一下你的服务端、客户端的内存开销。
先用 cat proc/meminfo 查看,重点看 slab 内存开销。
```plain text $ cat /proc/meminfo MemTotal: 3922956 kB MemFree: 96652 kB MemAvailable: 6448 kB Buffers: 44396 kB …… Slab: 3241244KB kB
1
2
3
4
5
6
7
8
9
10
11
再用 slabtop 查看一下内核都是分配了哪些内核对象,它们每个的大小各自是多少。
当你这个实验真正做成功的时候,相信你能有很大的收获!
## 四、结束实验
实验结束的时候,服务器进程直接 ctrl + c 取消运行就可以。客户端代码可能需要手工关闭一下
```plain text
php clientd.php stop
最后记得取消为实验临时配置的新 ip
plain text php clientd.php ifdown
再重复一下本文所用的测试源码地址
地址: https://github.com/yanfeizhang/coder-kung-fu/tree/main/tests/network/test01
在该 Github 上除了测试源码以外,还有飞哥公众号里所有文章的链接,所以敬请 star !
另外飞哥建立了一个技术群,欢迎大家到群里来进一步交流。先加我微信(zhangyanfei748527), 我来拉大家。
相关文章
[漫画 一台Linux服务器最多能支撑多少个TCP连接](https://mp.weixin.qq.com/s?__biz=MjM5Njg5NDgwNA%3D%3D&mid=2247484207&idx=1&sn=50ae06628062bcdd5b2aff044f34fa80&scene=21#wechat_redirect) [漫画 理解了TCP连接的实现以后,客户端的并发也爆发了!](https://mp.weixin.qq.com/s?__biz=MjM5Njg5NDgwNA%3D%3D&mid=2247484310&idx=1&sn=025f7787f39a9eef322ab73c4687b910&scene=21#wechat_redirect) [漫画 花了七天时间测试,我彻底搞明白了 TCP 的这些内存开销!](https://mp.weixin.qq.com/s?__biz=MjM5Njg5NDgwNA%3D%3D&mid=2247484398&idx=1&sn=f2b0a9098673dad134a228ecf9a8ac9e&scene=21#wechat_redirect) - 说出来你可能不信,内核这家伙在内存的使用上给自己开了个小灶!
- 刨根问底儿,看我如何处理 Too many open files 错误!