理解 Reactor Design Pattern


看看wikipedia上的定义:

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模式就是由一个handler来并发的处理一个或多个输入请求的模式。这个handler分发并同步的调用于请求关联的处理器。

从这段话中可以看出reactor模式的大致结构:一个事件处理器(可demultupelx)以及可调用的请求处理器。

结构(摘自wikipedia):

  • 资源:任何可像系统提供输入或者消耗系统输出的资源
  • 同步事件分发器:用一个事件循环阻塞所有资源,当资源可用时就分发资源个响应的调度器
  • 调度器:处理注册和注销请求处理器,将从分发器的获取资源分发给关联的处理器
  • 请求处理器:处理获得的资源

下面就拿libevent来具体说说这个结构

resources:
对于libevent来说有信号、IO以及定时器,其中信号可归类到输入类,IO可分为输入和输出,定时器既不是输入也不是输出,只是利用了demultiplexer的接口。

demultiplexer:
各个系统皆有提供相应的API,并且多数可以设置阻塞超时。对libevent来说就是针对各个平台实现的一个统一接口dispatch,这个接口负责阻塞所有资源,直到其中某些资源可用。

dispatcher:
同样,libevent为各个平台提供了统一的接口adddel分别是从调度队列中注册和注销事件。

handler:
处理器部分,则是根据dispatcher的调度位于激活事件队列中的和特定时间按关联的回调函数。

虽然实现是单线程的,但是整个reactor可以在多线程环境中使用,具体可以有:one reactor per thread、one reactor(active task list) + thread pool等(可以看看memcached的实现)。


优势:
reactor实现和应用代码完全分离,这就使得应用组件可以分成模块,可重用;同时由于同步的调用请求处理器,这使得reactor可以应对简单的并发而不用增加多线程环境的复杂性。

局限:
由于翻转了控制流程,这使得debug变得困难;同时由于使用同步调用请求处理器,这就对大量的并发产生了限制(不能利用多核处理器的优势)。最后,reactor的可扩展性还受制于demultiplexer。


最后,除了reactor外,其实还用过另外一个东西asioProactor

PS

  • 同步: 小明点单交钱,然后等着取奶茶
  • 异步: 小明点单交钱,然后奶茶妹给了小明一个小票,等小明的奶茶做好了,再告诉小明来取
  • 同步阻塞: 小明点单交钱,然后等着取奶茶;小明在等着取奶茶的时候呢,啥都不干,就等着
  • 同步非阻塞: 小明在等着取奶茶的时候呢,翻出手机,一会翻翻微信朋友圈,一会瞅瞅奶茶妹有没有做好奶茶
  • 异步阻塞: 奶茶妹给了小明一个小票,然后小明还是傻等着
  • 异步非阻塞: 奶茶妹给了小明一个小票,然后小明翻出手机一直刷朋友圈, 过了一会儿奶茶妹说小明你的奶茶好了,过来拿,小明才放下手机去拿奶茶


转载请注明:Serenity » 理解 Reactor Design Pattern