项目一总结
项目整体
简单介绍
Linux下的主从Reactor模型高性能服务器框架。 采用One_Thread_One_Loop的Reactor模型,内部采用了epoll的IO复用模型,其中主Reactor线程接受新连接,将其加入从Reactor线程中,接受连接和处理事件区别处理,有效提高并发量。
项目碰到的难点
配置模块
描述
是一个json格式的配置文件读取的结构体config,内部的数据包括服务器的名称,开始绑定的第几个cpu,线程数量,日志等级、日志划分等级、日志路径;
配置的格式
日志文件的配置文件采用的是json的格式,并且c++采用的库是jsoncpp来进行解析的;
同步日志模块
描述
是一个同步的日志模块,可以实现日志的等级设置,日志的文件和终端输出,并且可以通过json格式的配置文件达到按小时、天、月来给日志分文件输出。
日志的等级

- TRACE:一种低级别的日志,是显示各个函数的调用关系的,很低级别的日志,所以很少使用。
- DEBUG:指出细粒度信息事件,对调试应用程序是非常有帮助的,主要用于开发过程当中打印一些运行信息。
- INFO:打印一些重要的信息,这个能够用于生产环境中输出程序运行的一些重要信息。
- WARN:表明会出现潜在错误的情形。
- ERROR:表明出现了系统错误和异常,无法正常完成目标操作。
时间轮与定时模块
时间轮描述
为了对于定时任务每次都需要循环检测是否到达了时间,采用时间轮的形式来解决这个问题。
时间轮的原理

- 轮子的分类:秒轮、分轮、时轮、天轮;
- 将大于60秒的定时任务包装成一个类(除了秒轮的其他轮),并且析构的时候执行该任务将分轮的任务加入到秒轮任务(只有秒轮任务才是真正的任务,其他轮上的是到时间插入到秒轮的这个任务);
定时模块描述
将定时任务插入到时间轮中,在事件循环中传入现在的时间,用现在的时间和上次执行时间轮的时间相比较,如果超过1s,那么时间轮就应该转动起来,并且将到时间的任务全部pop出去,然后就会触发任务;
定时任务与任务队列以及epoll循环的关系

事件以及事件循环模块
事件描述
将epoll_event的文件描述符fd与对应的事件触发封装成的一个类,使得框架更加方便
epoll的几个关键宏:
- EPOLLERR:发生错误
- EPOLLHUP:对端关闭
- EPOLLIN:有读读事件发生
- EPOLLOUT:有写事件发生
- EPOLLPRI:有外带数据发生
事件的功能
- 将fd与对应的读、写、关闭、错误事件相关联,封装成一个类方便操作;
- 将对应的读、写、关闭、错误事件分别实现一个虚函数,方便发生什么事件调用什么函数;
- 将事件的读、写使能实现,使能之后重新上树;
- 管道事件可以用于测试与触发epoll循环;
事件循环的描述
- 使用unordered_map存储所有的事件,并管理所有的事件;
- 管理epoll的循环,对epoll监听到的就绪事件(如读、写、关闭、错误)进行相应的操作;
- 管理任务队列,对不是在该线程的任务可以直接执行,不是的话加入任务队列,并且考虑了定时任务;
- 管理定时任务,使用的是时间轮,将定时任务插入到时间轮中;
- epoll循环、任务队列、定时任务的关系:在epoll循环之后是任务队列的处理,
这样能够保证对于所有链接的所有操作,都是在一个线程中进行的,不涉及线程安全问题!
SocketOpt模块
描述
SocketOpt是一个纯粹的工具类,封装了socket的各种工具,比如,将各个函数(socket、bind、accept、connect)进行封装。并且可以设置(setsockopt函数实现)Tcp的延迟确定、端口复用、非阻塞连接、保持长连接等。
其他
- accpet的参数设置的是一个最大值的宏
EventLoopThread与EventLoopThreadPool模块
EventLoopThread描述
将EventLoop循环放进一个线程中,在该线程中对EventLoop进行管理,比如设置线程是不是启动、线程号的记录等等
EventLoopThreadPool描述
将读取的静态配置中的线程池数量读取,并创建多个EventLoopThread,将其存储在一个thread_变量中,并且设置可以让所有的线程的EventLoop跑起来的函数作为启动函数,并且通过线程和cpu的绑定实现稳定的服务器性能。
EventLoopThreadPool功能简述
- 构造函数的时候实现线程的创建和管理
- 得到一个可以获取所有的EventLoop的函数,方便管理
- 实现线程和cpu的绑定以实现更好的稳定性能
Connection和Acceptor模块
Connection描述
一个对连接进行管理的模块,继承的是Event模块,是一个对连接事件的管理类。
Connection的功能
- 既然是继承的Event,表示他是一个事件,所以是一个fd与event相结合的类;
- 继承了Event,表示对新连接的管理,新连接的各个回调函数的设置;
Acceptor的描述
创建连接的类,可以挂载在某一个EventLoop的任务队列中实现服务器的绑定以及监听新连接的作用;
TcpServer模块
实现的是主Reactor部分的逻辑,实现的是将新连接封装成connection对象,然后挂载到子Reactor部分去。
TcpServer的功能逻辑
- 实例化Acceptor对象,然后将服务器接受连接的逻辑挂载在任务队列中,然后通过pipeEvent唤醒Epoll循环之后执行任务队列----开启监听(设置监听到新连接的回调函数);
- 有连接进来,将连接封装成connection对象,并且设置各种任务的回调(读、写、关闭、完成回调等)然后给到子线程的EventLoop中的任务队列,然后将任务设置为上子线程的EventLoop的树,监听连接的事件;
- 管理非活跃的连接,将任务添加进定时任务队列中,如果时间到了那么运行定时任务清楚非活跃的连接。
DNS服务模块
描述
实现的是本地解析DNS的过程,开启一个线程专门解析特定的域名得到IP,将IP存储在unordered_map的哈希表中,然后主线程去读取就好了
为什么设置这个功能
- 使得同一个域名可以不用多次请求;
- 后台解析线程的方式可以减少因为查询IP所浪费的时间;
- 通过配置文件实现定时的更新频率和时间的设置;

浙公网安备 33010602011771号