- epoll server [Main Epoll + Logic Epoll]
- [Ring | Vec] buffer [Read | Write]
- TcpConnection [Client]
- buffer 每个tcp连接的用户层缓冲buffer,会从socket buffer里面拷贝数据到用户层,后面TcpConnection类会来取数据 如何取解析buffer里面的流数据,也是TcpConnection需要做的事情
- common 错误码定义、一些全局变量
- epoll_server epoll总的实现,包括对TcpConnection类的管理
- interface 客户端的实现,包括组装请求,发送请求,获取服务端的相应并调用相关的回调函数
- logger 日志收集,开额外线程写日志文件
- queue multi-producer + multi-consumer lock-free queue,用来存用户的请求,工作线程消费请求
- tcp tcp连接的实现,需要实现解析tcp流的函数
- handler 处理解析出来的请求,并把结果回写到socket里面
-
每当有一个连接过来,主要listen的epoll会accept这个连接,并且把socket fd 以Round Robin的形式转发到每个线程的epoll里面,所以MainEpoll只用来处理连接
-
Clild Thread Epoll的作用是用来监听socket fd上面的可写事件的发生,如果有可写 事件,那么就会从socket fd里面读取数据到TcpConnection里面的ReadBuffer里面,然后再 尝试把Buffer里面的stream数据按照协议解析出来。解析出来的请求会放到MPMC Queue里面。
-
其他真实处理请求的线程会尝试从MPMC Queue里面取请求出来,并实例化Handler来处理 请求,并回写回复。
- 不想让接收连接的主线程堵塞。
- 对于接收数据的线程来说:如果一个请求的处理时间很长[代码有问题或者类似于查询持仓这样的请求],那么会影响后面的请求处理,所以接收数据的线程只接收并尝试解析数据,并把请求放到请求队列里面
- 对于真实处理请求的线程:这些线程就可以从队列里面拿请求出来,慢慢处理。但是也不能太慢,太慢的话,队列里面的消息处理不完,会让每个TcpConnection的ReadBuffer膨胀,在高压情况下(CPU全部打满),每个TCP连接的ReadBuffer会达到125MB以上,进而可能会OOM掉.(在服务很多连接的时候)
在CPU全部打满、正确处理完所有请求、正确回写所有请求的情况下,QPS大概是13-15W/s. 启动了10个client。全部都在一台机器上测试,如果分机器测试,QPS应该会更高一些.