项目一总结

项目整体

简单介绍

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所浪费的时间;
  • 通过配置文件实现定时的更新频率和时间的设置;
posted @ 2024-08-31 02:42  铜锣湾陈昊男  阅读(37)  评论(0)    收藏  举报