如何将gevent为一个工业级跨平台轻量级tcp网络服务框架?
摘要:ACE、libevent、boost::asio…… 看过了那么多重量级的库,你是否有时也在纳闷,有没有一款轻量级的跨平台网络服务库适合自己?特别是只管理本地连接的那种
前言
作为公司的公共产品,经常有这样的需求:就是新建一个本地服务,产品线作为客户端通过 tcp 接入本地服务,来获取想要的业务能力。与印象中动辄处理成千上万连接的 tcp 网络服务不同,这个本地服务是跑在客户机器上的,Win32 上作为开机自启动的 windows 服务运行;Linux 上作为 daemon 在后台运行。总的说来就是用于接收几个产品进程的连接,因此轻量化是其最重要的要求,在这个基础上要能兼顾跨平台就可以了。其实主要就是 windows,再兼顾一点儿 linux。
考察了几个现有的开源网络框架,从 ACE 、boost::asio 到 libevent,都有不尽于人意的地方:
a) ACE:太重,只是想要一个网络框架,结果它扒拉扒拉一堆全提供了,不用还不行;
b) boost::asio:太复杂,牵扯到 boost 库,并且引入了一堆 c++ 模板,需要高版本 c++ 编译器支持;
c) libevent:这个看着不错,还实际用这个做底层封装了一版,结果发版后发现一个比较致命的问题,导致在一些机器上服务启动失败,这个后面我会详细提到。
其它的就更不用说了,之前也粗略看过陈硕的 muddo,总的感觉吧,它是基于其它开源框架不足地方改进的一个库,有相当可取的地方,但是这个改进的方向也主要是解决更大并发、更多连接,不是我的痛点,所以没有继续深入研究。
与其在不同开源框架之间纠结,不如自己动手写一个。我的场景比较固定,不用那么面面俱到,简单罗列一下这个框架需要支持基本的功能:
同步写、异步读;
可同时监听多路事件,基于 1) 这里只针对异步 READ 事件 (包含连接进入、连接断开),写数据是同步的,因而不需要处理异步 WRITE 事件;
要有设置一次性和周期性定时器的能力 (业务决定的);
不需要处理信号 (windows 上也没信号这一说,linux 自己搞搞 sigaction 就好啦);
……
虽然这个框架未来只会运行在单机上,但我们不希望它一出生就带有性能缺陷,所以性能平平的 select 没能进入法眼,最终决定给它装上最强大的心脏:
Windows 平台: iocp
Linux 平台:epoll
ok,从需求到底层技术路线,貌似都讲清楚了,依照 libevent 我给它取名为 gevent,下面我们从代码级别看下这个框架是怎么简化 tcp 服务搭建这类工作的。
gevent 示例
gevent server
首先看一下服务侧的 sample:
1 #include "EventBase.h"
2 #include "EventHandler.h"
3
4 class GMyEventBase : public GEventBase
5 {
6 public:
7 GEventHandler* create_handler ();
8 };
9
10
11 class svc_handler : public GJsonEventHandler
12 {
13 public:
14 virtual ~svc_handler () {}
15 virtual void on_read_msg (Json::Value const& val);
16 };
这个服务的核心是 GMyEventBase 类,它使用了框架中的 GEventBase 类,从后者派生而来,只改写了一个 create_handler 接口来提供我们的事件处理对象 svc_handler,它是从框架中的 GEventHandler 派生而来,svc_handler 只改写了一个 on_read_msg 来处理 Json 格式的消息输入。
