反应堆模式

一、概念

  1、定义

  反应堆模式是一种对象行为类的设计模式,对同步事件分拣和派发。它是处理并发I/O比较常见的一种模式,用于同步I/O。

  其中心思想是将所有要处理的I/O事件注册到一个中心I/O多路复用器上,同时主线程阻塞在多路复用器上;一旦有I/O事件到来或者是准备就绪,多路复用器返回并将相应的I/O事件分发到对应的处理器中。

  2、Reactor事件处理机制

    Reactor是一种事件驱动机制,和普通函数的不同之处在于:应用程序不是主动的调用某个API完成处理,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口(这些接口又被称为"回调函数")。下面是事件驱动机制的模型图:

  

  事件驱动(回调)就是应用业务向一个中间人注册一个回调(event handler),当I/O就绪后,就向这个中间人产生一个事件,并通知此handler进行处理。这个中间人是由一个不断等待和循环的单独线程来承担,它接受所有的handler的注册,并负责向操作系统查询IO是否就绪在就绪后就调用指定的handler进行处理。这个中间人的名字就就叫做Reactor。

  3、优点

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

  • 相应快,不必为单个同步事件所阻塞,虽然Reactor本身也是同步的
  • 避免了多线程/进程的的切换开销
  • 可扩展性,可以方便的通过增加Reactor实例个数来充分利用CPU资源

二、反应堆模式组成

  

  

  1、Handler事件源

  Handler代表操作系统管理的资源,包括:网络连接、打开的文件、同步对象等等。事件可以来自外部,如客户端的连接请求、数据等,也可以来自内部,如定时器事件。

  2、Synchronous event demultiplexer同步事件分离器(事件多路分发机制)

  由操作系统提供的I/O多路复用机制,例如select和epoll,程序首先将其关心的句柄(即事件源)及其事件注册到event demultiplexer上,当有事件到达时,event demultiplexer会发出通知“在已经注册的句柄集中,一个或者多个句柄的事件已经就绪”;程序收到通知后,就可以在非阻塞的情况下对事件进行处理了。

  3、event Handler事件处理接口

  一个或多个模板函数组成的接口,描述了和应用程序相关的对某个事件的操作

  4、concrete event Handler具体的事件处理器

  事件处理接口的实现,实现了应用程序提供的某个服务

  5、Reactor反应器

  定义了一些接口,用于应用程序控制事件调度,以及应用程序注册、删除事件处理器和相关的描述符,是事件处理器的调度核心。Reactor管理器使用同步事件分离器来等待事件的发生。一旦事件发生,Reactor管理器先是分离每个事件,然后调度事件处理器,最后调用相关的模 板函数来处理这个事件。

三、NIO中的Reactor模式

  NIO中Reactor的核心是Selector。下面是一个简单的示例:

public class Reactor implements Runnable
{
    Selector selector;
    public Reactor() throws IOException
    {
        selector = Selector.open();
    }
    public void run()
    {
        try
        {
            while (!Thread.interrupted())
            {
                // 循环,等待事件
                selector.select();
                Set selected = selector.selectedKeys();
                Iterator it = selected.iterator();
                while (it.hasNext())
                    // 调用handler,处理事件
                    dispatch((SelectionKey) (it.next()));
                selected.clear();
            }
        } catch (IOException ex)
        { /* ... */
        }
    }
    void dispatch(SelectionKey k)
    {
        Runnable r = (Runnable) (k.attachment());
        if (r != null)
            r.run();
    }
}

四、参考资料

  1、http://ifeve.com/netty-reactor-4/

  2、http://www.2cto.com/kf/201504/389198.html

posted @ 2016-07-27 17:04  温布利往事  阅读(2706)  评论(0编辑  收藏  举报