开源项目 EchoLib并发服务器框架(轻量级Muduo)

github源码https://github.com/Worthy-Wang/EchoLib


项目简介

该并发服务器框架模仿 陈硕的Muduo库来实现,采用reactor + threadpool的模式,是一个能适应密集计算的并发服务器框架。该项目主要分为两个部分:reactor+ threadpoolreactor负责将TCP连接进行封装,并采用Event-Loop模式结合epoll多路复用进行监听,然后注册相应的回调函数,并且将IO线程计算线程分离。threadpool部分基于Posix线程实现,会依次对互斥锁条件变量任务队列线程线程池类进行封装,同时注册相应的回调函数
在这里插入图片描述


项目详细描述

该项目主要分为两个部分,reactor + threadpool

  • reactor网络库部分

reactor部分主要将TCP网络编程中的socket,bind,listen,accpet与SocketIO等操作进行封装,并且使用Event-Loop模式结合多路复用epoll进行监听描述符,之后再为reactor注册相关的回调函数
回调函数有三个:

  1. 新连接产生时的回调函数;

  2. 连接发来消息时的回调函数;

  3. 连接终止时的回调函数。

在进行完以上操作之后reactor就可以监听端口,处理新连接,处理对端发来的消息,处理连接断开的情况。

reactor监听的描述符有三种类型:

  1. acceptor_fd:用于产生新连接的描述符,新的TCP连接产生之后reactor会接收到一个新的描述符fd,把这个描述符加入监听队列;
  2. 已连接 fd:用于接收已连接的TCP对端发送过来的信息。接收该消息后会将其封装成任务添加到线程池中的任务队列,这也是reactor 与 threadpool之间的桥梁。我的搜索引擎项目也就是将客户端发送的消息封装成任务添加到线程池的任务队列。
  3. event_fd: 计算线程不能够直接给客户端发送消息,所以需要将计算线程与IO线程进行分离(设置eventfd用于线程间通信)。当计算线程执行任务完成后,会通过event_fd发来IO请求,reactor(也就是IO线程)才会接收信息再发送给客户端。

  • threadpool线程池部分

线程池的部分主要对Posix线程进行了封装,对多线程以下五个部分进行了封装:

  1. mutex互斥锁的加解锁封装,并且利用对象的生命周期实现自动加解锁,以防忘记解锁之类的;

  2. 条件变量condition的封装,实现线程间的同步。

  3. 任务队列的封装,将线程间的同步与互斥都隐藏在任务队列的入队和出队中,并且设置好任务的安全退出机制,确保所有的线程在退出时都能够被安全的join

  4. 线程类的封装,采用基于对象线程类的设计,通过注册回调函数的方式实现线程类的功能。

  5. 线程池类的封装,将任务队列与多个线程封装在一起,许多个线程争抢并执行任务队列中的任务。


学习流程推荐

建议依次从Version1.0 开始学习,一直学习到 Version5.0,每一个版本都会在原版本上新增更多内容。依次递进的学习,更有利于掌握该并发服务器模型。之后再去学习陈硕老师的muduo库,便是更加得心应手。


技术核心

  1. 搭建线程池框架

技术亮点:基于对象线程池设计Posix线程同步与互斥任务队列自动加解锁类线程安全退出机制bind回调函数 智能指针unique_ptr

  1. 搭建服务器框架

技术亮点:基于对象服务器设计bind回调函数socket网络编程TCP连接IO多路复用epolleventfd(IO线程与计算线程分离)客户端安全退出机制智能指针shared_ptr


补充:不同 并发服务器模型的类别差异
在这里插入图片描述

Reactor/Proactor模式是什么?

Reactor模型与Proactor模型都是并发服务器模型,Reactor模型属于同步IO,Proactor模型属于异步IO。

  • Reactor

Reactor模型处理请求的流程:

  1. Reactor首先需要注册相关 事件处理器(Handler)。

  2. 事件分离器监听就绪事件。(如epoll)

  3. 当就绪事件发生时,调用相应的事件处理器,也就是回调函数。

总结一下,就是 注册->监听->调用回调函数。


  • Proactor

Proactor模型处理数据的流程:

  1. Proactor首先初始化异步程序,并注册相关的事件处理器(Handler)。

  2. 事件分离器(如epoll)监听事件,但注意并不是监听 就绪 事件,而是监听 完成 事件,这是Proactor不同的一点

  3. 事件分离器在等待 完成 事件的时候,会调用内核将数据放到 缓冲区 中,当 完成事件 发生时,调用事件处理器 直接从 内存缓冲区 读写数据。这也是Proactor不同的一点,并不会进行实际的IO读写操作,而是直接从内存缓冲区读取数据

总结一下:仍然是 异步+注册->监听完成事件->调用回调函数处理缓冲区。


  • 总结 Reactor VS Proactor
  1. Reactor关注的是就绪事件;Proactor关注的是完成事件。

  2. Reactor 需要进行实际的读写操作;Proactor不会进行实际的读写操作,而是直接从内存缓冲区读写。

  3. Reactor编程相对简单;Proactor编程相对复杂,且由于需要稳定的内存缓冲区 造成不稳定性,同时目前Linux下的异步IO仍然是使用epoll实现的。

所以,目前Linux下实现的高并发网络编程都是以Reactor模型为主。

相关知识补充说明
Reactor的常用模型有以下几种:

  1. 单Reactor单线程模型
    在这里插入图片描述
  2. 单Reactor多线程模型
    在这里插入图片描述
  3. 主从Reactor多线程模型
    在这里插入图片描述
    此处也就是多reactor的模式,因为accept接收套接字的时候会有阻塞的情况,所以专门分出一个reactor来进行accept接收套接字;另外的reactor专门监听这些套接字集合是否就绪。

Reactor模型中有三大角色

  • Reactor:负责监听事件,当有事件就绪时调用相应的回调函数。(事件就绪分为 连接就绪,读就绪,写就绪)
  • Acceptor:负责处理客户端的新连接,并将文件描述符传递给Reactor。
  • Handler:事件处理器,是一种通过回调函数(钩子函数)实现的事件处理机制,当handle(文件描述符)上有事件发生时,便会执行该回调函数。

关于英文资料中Reactor/Proactor模型专业名词解释

  • Handle:Handle在Linux中称为文件描述符,在Windows中称句柄,含义相同。Handle是事件的发源地,发生在handle上面的事件可以有connection(连接),read for read(读就绪),read for write(写就绪)。
  • Synchronous Event Demuliplexer:同步事件分离器,本质上属于系统调用。如IO多路复用 select/poll/epoll等方法。
  • Event Handler:事件处理器,是一种通过回调函数(钩子函数)实现的事件处理机制,当handle上有事件发生时,便会执行该回调函数。
  • Dispatcher:初始分发器,也就是reactor,提供了注册,删除,转发Event Handler的方法。当Synchronous Event Demuliplexer 检测到 handle 上面有事件发生时,便会通知dispatcher调用特定的回调函数。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值