网络编程大并发实战-C10K

网络通信是由用户需求推动,早期,大家都玩单机游戏,上个互联网有个上百人就算是比较大型应用,当时并没有那么大的需求。但是,随着PC普及,互联网的爆发期,游戏经历单机,到局域网,到互联网多人大型游戏;互联网的发展也从1.0的浏览下网页,到2.0的各种社群交互互动,C10K问题首先涌现。

问题

早期的IO模型基本都是一个进程或者一个线程一个连接,C10K,物理资源是他的天花板。不管是否分布式,那都是及其耗费物理资源,成本巨大。

分析

既然问题是由于进程或者线程引起的物理资源问题,那么突破口也资源这里,IO线程模型使用就是让一个进程或者线程处理多个连接,网络IO就使用多路复用。在早期由一个比较成熟的就是select 模型,而后又发展出了poll,epoll,同时还有aio,这些在前面章节都有涉及,在这里我们就直接上代码来验证他们能否解决C10K问题,并进行分析。在此我们通过写一个简单的网络库,来验证各种实现方式模型是否可行。简单就叫其link吧。使用reactor 模式,该库包含select,poll,epoll等。线程模型为单线程接受处理,单线程接受多线程处理通信两种方式。统一level_tringer触发,统一处理成事件回调模式。通过测试对比每种实现方式来看看是如何解决C10K,及其中的一些问题及奥秘的。

select

在 linux 下使用select 有诸多连接限制,并且修改麻烦,同时 select 模型 在windows 也是参照linux下的select 模型移植过来的,并且windows 下只要重新定义 FD_SETSIZE 大小就可以改变原来 每个 接收所以就在本机windows 下测试。

逻辑:建立完成所有连接后,所有连接同时发送一个业务注册包,服务收到后立马应答。

客户端发送10239个链接,服务端稳定的接收了该10239个连接并注册成功,但是其响应时间有点延迟:

结果:内存占用连接数10239 大概100M,CPU 0- 5%的波动。

连接数 127 1023 10239 注册数 128/128 1023/1023 10239/
10239
连接耗时(MS) 23 179 4230 注册耗时
(MS)
16 36 7590

测试环境:以上测试数据在两台局域网的PC机器中进行,i5双核4线程,8G内存,其中还开了其他应用不是非常纯净,服务器测试程序开了1个连接接收线程,4个连接处理线程。

分析:同时测试服务器应该还有可改进的空间,为了能把select ,epoll等所有模型都放到LINK 库中,回调嵌套太多,内存拷贝等还有很多可优化,同时服务器调优下。所以如果再认真点做好,windows 下的这个 非阻塞 select 模型C10K 都应该不是问题,至少连接上,可以处理,但是发包应答的延迟还是挺致命的,有机会后续可以优化看看,那么如果直接使用windows提供的eventselect 模型应该更加容易达成这个结果了。当然这个结果已经出乎意料,linux 下的select 没有试过,但是windows下的这个结果,

结论:select模型下,初略估算C10K的连接,每秒2000的活跃连接并发还是能轻松支持。

epoll

架构模型同上面的,在做这个测试之前我们其实已经知道epoll 是高效能的,所以100,1000级别的咱就没必要测试了,直接看下 C10K的测试结果

结果:内存占用连接数10239 大概79M,CPU 0- 5%的波动。

连接数 10239 注册数 10239
连接耗时(ms) 469 注册耗时
(ms)
454
测试环境:Intel(R) Xeon(R) CPU E5-2430 0 @ 2.20GHz,4核,8G内存,测试服务器非常不纯净,将就用,服务器测试程序开了1个连接接收线程,4个连接处理线程。
结论:还是非常轻松的就能支持C10K连接,并且并发轻易上20K。

总结:

改测试库写的非常仓促,还是有很多改进空间。如果只是需要C10K的连接数的话,select 跟epoll 都能满足需求,就目前测试情况来看,select 也没有传说中的不稳定,还是挺稳定,但是select 并活跃并发数虽然也能上到 10K,但是其相应时间应该已经超出了正常业务场景的需求,所以如果并发数量不多,使用select 也能一战,这也是为什么以前的游戏服务器,虽然 epoll ,IOCP已经成熟的情况下,select 还是能撑起半壁江山,也是不无道理。所以如果要上生产大并发的话,epoll 还是不二选择。