muduo中的reactor模式实现浅析

muduo中的reactor模式实现浅析

最近刚刚看完了陈硕大神的《Linux多线程服务端编程》,对muduo源码也略有阅读,故作此总结。

Reactor模型

先来看看定义:

The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.

简单地说,reactor就是由一个中控器去多路复用监听多个事件,事件触发后,中控器将事件转发给某个线程处理。reactor的演化可以大致分为三步:

  • 方案1:单 Reactor 单线程;
  • 方案2:单 Reactor 多线程;

  • 方案3:多 Reactor 多线程;

上述方案中,方案1不能利用多线程,性能受影响,不适用高性能服务器场合。

方案2采用线程池来处理业务,但是网络读写仍由主线程处理,性能上问题不大,因为单线程读写一般不比多线程读写慢,但是这引起资源竞争问题,因为线程池中的线程要去竞争对socket的读写,会带来同步开销。

所以muduo选用了方案3,也就是所谓的one loop per thread,有一个main Reactor负责accept连接,已建立的连接由sub Reactor全权控制:当一个新的连接到来,main Reactor只负责把它分配给某个sub Reactor,然后不再关心该连接,所有在该连接上的操作由sub Reactor完成这也带来了编码上的简化。

那么muduo是如何实现的多Reactor多线程呢?

muduo实现——单Reactor单线程

其实muduo本身支持上述的全部三种方案,而且只需要简单的几行代码就可以完成切换,具体用法可见 书中$6.6详解muduo多线程模型。

你应该了解这几个类(都在muduo/net包下):

  • Channel,负责一个sockfd的IO事件分发,但不拥有sockfd。
  • Poller,是对IO多路复用(即poll、epoll等)的封装。
  • EventLoop,驱动类,和线程是1:1关系。

三者的关系是这样的(下面的代码中会忽略不重要的部分,例如定时器、时间戳、各种断言和错误处理等):

EventLoop类拥有一个Poller类成员,创建EventLoop对象时,其构造函数会初始化此数据成员poller_,

EventLoop::EventLoop() : /* ... */ poller_(Poller::newDefaultPoller(this)) {
   
  /* ... */
}

由“第三方”来创建sockfd,依此sockfd创建一个新的Channel,并将此Channel绑定到一个EventLoop对象上,

int main() {
   
  EventLoop loop;
  int sockfd = /* ... */
  Channel channel(&loop, sockfd);
  /* ... */
}

此时的绑定是假绑定,loop对象并不知道此channel的存在,直到启用对channel的多路复用监听时:

int main() {
   
  /* ... */
  channel.setReadCallback(timeout); // 监听某种事件前必先注册相应的事件处理回调
  channel.enableReading();
  loop.loop(); // 开始eventloop,循环处理事件
  /* ... */
}

Channel::enablexxx()会调用Channel::update(),进一步调用EventLoop::updateChannel(this),实现了将channel管理的sockfd注册进Poller:

void Channel::update()
{
   
  addedToLoop_ = true;
  loop_->updateChannel(this); // loop_数据成员是在构造当前Channel对象时绑定的EventLoop对象
}

/* ... */
void EventLoop::updateChannel(Channel* channel)
{
   
  assert(channel->ownerLoop() == this
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值