这些天在做公司项目和毕业设计的时候,因为要用Python写大量的网络服务,尝试了各种能用在Python下的网络库、框架和中间件。折腾了这么久,渐渐感觉到,目前的这些鼎鼎有名的通用型网络通信解决方案都有这种那种的问题,通用的代价就是妥协,妥协的结果就是会带来一堆不符合我需求的以及我不需要的东西。对于一个立志于长期运行的大型应用来说,造出一个完全符合自己需求的轮子几乎是一个必然的事情。而这个轮子完善后也会成为一个特定领域的通用解决方案,再以后随着运行环境、系统底层、应用模式的转变(譬如异步IO从select发展到epoll,譬如c++模板元编程的大行其道),这个轮子也变得不合时宜,再也跟不上时代的脚步,它就可以果断得光荣退休了,江山代有人才出,后来事自然不用它担心。下面说下我所遇到的那些问题。
我要搭建的服务之一就是一个要支持高并发的HTTP服务器。最显而易见的方法自然是用Apache(Nginx)+FastCGI(WSGI)+Flup+Django这样的组合,但现在的情况是,这个服务是只需要处理不相关的一系列POST请求,不需要支持Session,不需要格式化HTML,不需要返回静态文件。这样一来,Django、web.py这些重型的Web框架就都成了累赘,然后我发现了Tornado(http://www.tornadoweb.org)这个HTTP服务器。Tornado现在由Facebook维护,其定位就是高并发服务器,从大量的评测结果来看,它从性能上超过了其它对手至少2倍以上,包括基于传说中的Python网络框架一哥Twisted的那些。Twisted存在的问题,我后文中会详细说明。Tornado高性能的秘诀就在于它对epoll的高效处理,它基于epoll自己实现了一套IO事件循环机制,对所有的HTTP请求都是异步处理。而对于GIL锁带来的无法有效利用多核的问题也很好解决,多跑几个Tornado进程,使用Nginx做下负载均衡即可。我的另一个需求是需要通过HTTP连接帐号服务器做验证,这个耗时的过程必然要使用异步连接,否则阻塞时间对性能的影响是致命的。这点也不用担心,Tornado支持异步HTTP请求。
另一个需求就是,我需要跟数据库通信,数据库我们用的是Redis(http://code.google.com/p/redis/),也是一个高性能高并发的一个东东。现有的Redis的Python客户端只有2个,其中一个是用的底层Socket同步连接,这点无疑会降低服务器的并发数。另一个客户端是异步的,但是它是用twisted写的,而且很久没有更新了,许多Redis的新特性都没有支持。要知道,2个异步事件框架是无法共存的,这就注定了twisted无法用在我要写的HTTP服务器中。这就是我想造的第一个轮子,使用Tornado底层事件循环的异步Redis数据库客户端。
我的另一个需求就比较纠结了,HTTP服务器需要同大量的应用服务器进行通讯,而应用服务器要做大量的处理工作,比较耗时,所以这个连接也要是异步的。其实我需要的就是一个异步RPC机制,另外还需要考虑异构环境(x86与x64系统之间、python与c++之间)的问题。现在采用的方法又是一个通用的解决方案ICE(http://www.zeroc.com/)。ICE的问题也是通用解决方案的通病,太过臃肿,而且不是一般的臃肿。ICE的定位是一个分布式中间件,它不仅仅包括一个RPC,还有各种的命名服务、配置服务等等。而ICE的异步RPC实现方案我也不太满意,它的做法是在后台跑一个事件接收线程,无法融入到整个异步事件处理框架中去。所以,我想造的第2个轮子就是一个使用Tornado底层事件循环的RPC客户端。
为什么一直要对Tornado的底层事件循环念念不忘?因为它的高性能给我留下了深刻的印象。但直接那它来写别的网络服务也不是一件很简单的事情,因为这是在是对epoll的一层很薄的封装。这就是我要造的第3个轮子,基于Tornado IO Loop的一个异步网络库。上文说到了一哥Twisted,Twisted所存在的问题其实是与ACE一脉相承的,因为Twisted是模仿ACE而来的。ACE是这类异步网络框架的开山鼻祖,曾经光环满身,而现在也遭到了口诛笔伐,譬如“学之者生,用之者死”。ACE是得了模式综合症,用了大量的OO设计模式,结果就导致整个的程序风格完全被ACE所控制,Twisted也是这样。这几年,C++领域的ASIO横空出世,用模板元编程实现了一个优雅的异步网络框架,避免了ACE那样大量丑陋的继承。而在Python这样的动态语言下,更无须被OO的规则所束缚,面向对象设计模式更多的是解决静态语言的设计问题,但这些问题在动态语言里并不存在。所以,我要造的这个网络库是参见了ASIO的,模板元编程能实现的,动态语言也可以实现。我目前需要的网络库是什么:只支持Linux,只支持epoll,只支持IO复用+事件循环的方式,不支持同步IO,不需要线程安全(因为在Python下多进程优于多线程)。再接下来,自然是要以这个网络库为基础,实现上述的2个轮子,另外把我那个已经用twisted实现的RPC框架移植过来。
轮子虽好,可不要贪杯哦~