思路
底层,网络通讯层:
采用epoll+non-block socket 进行多路复用。采用redis的event loop框架,稍作修改。
这一层干嘛呢,就干一件事儿,监听,然后处理链接上来的socket,读取请求数据数据。
这个地方,我现在有另外一个想法,两种方式去实现:
- 第一种,主线程去 accpet,epollwait client fd 的连接,连接上来之后,读取数据的工作,是不是放到IO Trans thread 中去处理。这个新链接上来的clientfd 我们将其挂载到 io thread 自己内部维护的epoll中。
- 第二种,主线程去读 client fd 中的io数据,但是不解析,将读来的数据流转到 transthread 中去解析。
- 说句心里话,第二种貌似比较普遍,自己写着玩儿,我们不妨试试第一种。主线程thread + 一个epoll fd。IO thread 2个或者4个,各自一个epoll fd。
IO trans 层
这一层 Trans thread:
- 第一,读取IO数据。
- 第二,解析IO数据。原始的二进制数据,解析成HTTP 的packet。
- 第三,其实也算不上第三,就是TCP的层面会出现粘包分包什么的,这是这一层的稍微复杂一点的逻辑,要将其处理掉。
worker 层
这一层,我的想法是这样。类似tomcat一样。我们怎样处理http的请求呢,模块化处理。我们预定义一些规则,我们把http的request对象与空的response对象作为两个参数,采用动态加载的方式,根据路由的路径,去动态加载指定的so,比如index.so,然后找到指定的函数,如下
int index(HttpRequest const*request,HttpResponse * response);
这样的话,谁要是想往这个框架里面添加模块,这编译出这样一个so出来,在指定目录下创建好对应的目录,然后把SO放进去就OK了。
功能模块路由模块
为了简单,我们会把规则制定得强制一些,傻瓜一些。
http层面的处理
我们尽量把HTTP层面需要处理的一些逻辑,都放进模块中。也就说,我们的框架,其实并不需要太考虑HTTP协议的内容,尤其是一些复杂的时序之类的,保持连接之类的,session cookie 之类的。我们把请求解析出来,传递给模块了,接下来,请各模块自己去处理,这样来简化我们框架层的工作。
工具模块
我们这个不管怎么样,尽量纯手撸,减少依赖。
多线程:线程池,支持C++11 吧,好写,跨平台,单元测试,也好调。
日志模块:做一个线程安全的吧,我们用C的那一套FILE API来做,把内部的buf大小给调大一些。回头如果有有必要,再或优化。
配置模块:手动解析一个类似 ini 格式的文件
实例池
缓存buf池
EventLoop 架构模块
Http message 解析模块
路由模块
动态加载器模块
要不要跨平台呢?先不考虑跨平台了,就epoll+支持C++11的linux了。
我们先不考虑高可用。回头需要的时候,再去确认流言协议,up/down等。现在就当成单个功能节点去处理。
后面就开撸。