zony.me

C1000K 实战,基于 Libev

最近公司接到一个新项目,是基于Socket通信的GPS实时记录系统。实际设备台数是在20W左右,但是自己并没有对实时性要求这么高的高并发服务器软件设计经验,只能硬着头皮先进行测试开发试一下。 技术选型的话,当时是直接想使用Windows下面的IOCP,因为自己对C#这块比较熟悉,不过经过测试,在WindowsServer上面的测试结果并不理想,可能是自己水平不到家吧(笑)。关于高性能的IOCP编程大家可以参考这位仁兄的文章,写得很不错,而且也有实例:(C#高性能大容量SOCKET并发(一):IOCP完成端口例子介绍) 之后查阅了相关的技术资料和各类博客,发现Linux更适合做此类系统,所以选择了CentOS 7.x 64bit作为开发系统,高并发主要在于对Socket的监听一定要及时,所以Epoll是最好的选择。但是博主并不想直接再写一次Epoll了,相关Epoll进行高并发编程的可以参考**这篇文章**很不错的实例。所以我直接选择了Libev库作为底层的事件库,进行事件监听。

首先我们要实现C1000K的话,得对Linux的内核参数进行调优,怎么调? 第一步,调整系统单个进程最大打开的文件句柄数量:

Shell
vim /etc/security/limits.conf

在最末尾加入:

Shell
* soft nofile 1048576
* hard nofile 1048576

因为Linux下面一皆文件,即便是我们的Socket网络套接字也是属于文件句柄这个范畴的,默认大小可以通过ulimit -n查看,默认是1024个,对于我们百万并发的服务器来说显然是不够的。 这里的星号(*)代表的是对所有用户生效,当然你也可以手动指定用户,soft是警告阀值,而hard则是实际生效的阀值,在这里我们为了方便直接都改成一样的就可以了。

第二步,设置系统所有进程最多同时打开的句柄数量限制:

Shell
echo "fs.file-max = 1048576" >> /etc/sysctl.conf

之后执行以下命令使其生效:

Shell
sysctl -p

第三步,TCP参数调优:

Shell
echo "net.ipv4.tcp_mem = 786432 2097152 3145728" >> /etc/sysctl.conf
echo "net.ipv4.tcp_rmem = 4096 4096 16777216" >> /etc/sysctl.conf
echo "net.ipv4.tcp_wmem = 4096 4096 16777216" >> /etc/sysctl.conf

tcp_rmem是TCP读取缓冲区,tcp_wmem是发送缓冲区,他们的单位都是字节,第一个是最小值,第二个是默认值,第三个是最大值,这里分别设置为4K,4K,16MB。 tcp_mem是TCP内存大小,单位是页,一页为4096字节。

实际测试环境中,据观察大概在99万个连接左右的时候(零头不算),进程被杀死,触发out of socket memory错误(dmesg命令查看获得)。每一个连接大致占用7.5K内存(下面给出计算方式),大致可算的此时内存占用情况(990000 * 7.5 / 1024K = 7251M)。

未完待续

C1000K 实战,基于 Libev
作者 Zony · 发布于 2016-11-21
Licensed under CC BY-NC-SA 4.0
← 上一篇C# 如何实现URL编码?下一篇 →对于 Task 并行操作所遇到的问题