前言

网络模型一文中,我们介绍了多种网络IO模型,其中包括IO多路复用模型,在此基础上,本文将介绍两种高性能IO模型:Reactor和Proactor,Reactor应用于同步IOProactor应用于异步IO

Reactor模型

普通函数调用流程如下:

reactor设计(高性能IO模型Reactor和Proactor)(1)

reactor_normal

Reactor模型一种事件驱动(回调)机制:程序不主动调用某个API处理,而是相应事件发生,Reactor主动调用应用程序注册的接口进行处理。

中心思想:将所有要处理的IO事件注册到一个IO多路复用器上,同时主线程/进程阻塞在多路复用器上。一旦有IO事件到来或准备就绪,多路复用器返回并调用相应的事件处理函数

reactor设计(高性能IO模型Reactor和Proactor)(2)

my_reactor

接下来将具体介绍三种Reactor模型

Reactor单线程模型(Single threaded version)

reactor设计(高性能IO模型Reactor和Proactor)(3)

Reactor模型三个重要组件

该模型中,Reactor线程既要负责监听新连接的到来,又要dispatch请求到handler中;

消息处理流程如下:

以下为一个简化版的Reactor单线程模型

//reactor初始化创建多路复用器 intreactor_init(structreactor*r){ r->epfd=epoll_create(1); } //reactor驱动 intreactor_run(structreactor*r){ if(r==NULL||r->epfd<0||r->events==NULL) return-1; structepoll_eventevents[1024 1]; while(1){//死循环 //有事件到来时通过epoll_wait返回 intnready=epoll_wait(r->epfd,events,1024,1000); if(nready<0){ continue; } for(i=0;i<nready;i ){ structevent_data*ev=(structevent_data*)events[i].data.ptr; if(events[i].events&EPOLLIN)//availableforread ev->callback(ev->fd,events[i].events,ev->arg);//调用读事件的回调函数处理 if(events[i].events&EPOLLOUT)//availableforwrite ev->callback(ev->fd,events[i].events,ev->arg);//调用写事件的回到函数处理 } } return0; }

Reactor单线程模型只适用于小容量应用场景,但对于高负载高并发场景并不适用,主要原因:

为了解决上述问题,演进出单Reactor多线程模型(线程池)

Reactor多线程模型(Multithreaded Designs)

reactor设计(高性能IO模型Reactor和Proactor)(4)

消息处理流程如下:

相对于第一种模型来说,在处理业务逻辑,也就是获取到IO的读写事件之后,交由线程池来处理,handler收到响应后通过send将响应结果返回给客户端。这样可以降低Reactor的性能开销,从而更专注的做事件分发工作了,提升整个应用的吞吐量

但是这个模型存在问题如下:

为了解决性能问题,产生了第三种主从Reactor多线程模型

主从Reactor多线程模型(Multiple Reactors)

reactor设计(高性能IO模型Reactor和Proactor)(5)

将Reactor分为两部分

Nginx、Swoole、Memcached和Netty都是采用这种实现。

消息处理流程,如下:

Reactor模式是编写高性能网络服务器的必备技术之一,具有以下优点:

Proactor模型

事件分离器只负责发起异步读写操作IO操作本身由操作系统来完成,需要将用户定义的数据缓冲区地址和数据大小传给操作系统,其才能从中得到写出操作所需数据,或写入socket读到的数据。

事件分离器捕获IO操作完成事件并传递给对应事件处理器,由事件处理器获取IO操作结果,并对数据进行处理。

Proactor工作流程如下:

  1. 处理器发起异步操作,并关注IO完成事件
  2. 事件分离器等待操作完成事件
  3. 分离器等待过程中,操作系统利用并行的内核现场执行实际的IO操作,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操作完成
  4. IO完成后,通过事件分离器呼唤处理器
  5. 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分离器

Proactor模型最大的特点是使用异步IO,所有IO操作都交给系统提供的异步IO接口执行。工作线程仅负责业务逻辑。

优点:给工作线程带来了更高的效率;

缺点:

Reactor和Proactor的相同点都是通过回调方式通知有IO事件到来,并由handler进行处理,

不同点在于Proactor回调handler时IO操作已经完成(异步),Reactor回调handler时需要先进行IO操作(同步)

例如:Reactor中注册读事件,当fd可读时,调用者需要自己调用read读取数据,而Proactor在注册读事件时,同时会提供一个buffer用于存储读取的数据,那么Proactor通过回调函数通知用户时,用户无需再调用read读取数据,数据已经再buffer中了。

参考

nio

Reactor 和 Proactor

,