`
bluepeer
  • 浏览: 74467 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

[转]Reactor模式和NIO

    博客分类:
  • JAVA
阅读更多


 Scalable IO in Java : http://www.jdon.com/concurrent/nio.pdf

[引] 板桥里人


当前分布式计算 Web Services盛行天下,这些网络服务的底层都离不开对socket的操作。他们都有一个共同的结构:
1. Read request
2. Decode request
3. Process service
4. Encode reply
5. Send reply

经典的网络服务的设计如下图,在每个线程中完成对数据的处理:



 

但这种模式在用户负载增加时,性能将下降非常的快。我们需要重新寻找一个新的方案,保持数据处理的流畅,很显然,事件触发机制是最好的解决办法,当有事件发生时,会触动handler,然后开始数据的处理。

Reactor模式类似于AWT中的Event处理:




Reactor模式参与者

1.Reactor 负责响应IO事件,一旦发生,广播发送给相应的Handler去处理,这类似于AWT的thread
2.Handler 是负责非堵塞行为,类似于AWT ActionListeners;同时负责将handlers与event事件绑定,类似于AWT addActionListener

如图:


 

Java的NIO为reactor模式提供了实现的基础机制,它的Selector当发现某个channel有数据时,会通过SlectorKey来告知我们,在此我们实现事件和handler的绑定。

我们来看看Reactor模式代码:

public class Reactor implements Runnable{ 
  final Selector selector; 
  final ServerSocketChannel serverSocket; 


  Reactor(int port) throws IOException { 
    selector = Selector.open(); 
    serverSocket = ServerSocketChannel.open(); 
    InetSocketAddress address = new InetSocketAddress(InetAddress.getLocalHost(),port); 
    serverSocket.socket().bind(address); 

    serverSocket.configureBlocking(false); 
    //向selector注册该channel 
     SelectionKey sk =serverSocket.register(selector,SelectionKey.OP_ACCEPT); 

    logger.debug("-->Start serverSocket.register!"); 

    //利用sk的attache功能绑定Acceptor 如果有事情,触发Acceptor 
    sk.attach(new Acceptor()); 
    logger.debug("-->attach(new Acceptor()!"); 
  } 


  public void run() { // normally in a new Thread 
    try { 
    while (!Thread.interrupted()) 
    { 
      selector.select(); 
      Set selected = selector.selectedKeys(); 
      Iterator it = selected.iterator(); 
      //Selector如果发现channel有OP_ACCEPT或READ事件发生,下列遍历就会进行。 
      while (it.hasNext()) 
        //来一个事件 第一次触发一个accepter线程 
        //以后触发SocketReadHandler 
        dispatch((SelectionKey)(it.next())); 
        selected.clear(); 
      } 
    }catch (IOException ex) { 
        logger.debug("reactor stop!"+ex); 
    } 
  } 

  //运行Acceptor或SocketReadHandler 
  void dispatch(SelectionKey k) { 
    Runnable r = (Runnable)(k.attachment()); 
    if (r != null){ 
      // r.run(); 

    } 
  } 

  class Acceptor implements Runnable { // inner 
    public void run() { 
    try { 
      logger.debug("-->ready for accept!"); 
      SocketChannel c = serverSocket.accept(); 
      if (c != null) 
        //调用Handler来处理channel 
        new SocketReadHandler(selector, c); 
      } 
    catch(IOException ex) { 
      logger.debug("accept stop!"+ex); 
    } 
    } 
  } 
} 

 

以上代码中巧妙使用了SocketChannel的attach功能,将Hanlder和可能会发生事件的channel链接在一起,当发生事件时,可以立即触发相应链接的Handler。

再看看Handler代码:

public class SocketReadHandler implements Runnable { 
  public static Logger logger = Logger.getLogger(SocketReadHandler.class); 

  private Test test=new Test(); 

  final SocketChannel socket; 
  final SelectionKey sk; 

   static final int READING = 0, SENDING = 1; 
  int state = READING; 

  public SocketReadHandler(Selector sel, SocketChannel c) 
    throws IOException { 

    socket = c; 

    socket.configureBlocking(false); 
     sk = socket.register(sel, 0); 

    //将SelectionKey绑定为本Handler 下一步有事件触发时,将调用本类的run方法。 
    //参看dispatch(SelectionKey k) 
    sk.attach(this); 

    //同时将SelectionKey标记为可读,以便读取。 
    sk.interestOps(SelectionKey.OP_READ); 
    sel.wakeup(); 
  } 

  public void run() { 
    try{ 
    // test.read(socket,input); 
      readRequest() ; 
    }catch(Exception ex){ 
    logger.debug("readRequest error"+ex); 
    } 
  } 


/** 
* 处理读取data 
* @param key 
* @throws Exception 
*/ 
private void readRequest() throws Exception { 

  ByteBuffer input = ByteBuffer.allocate(1024); 
  input.clear(); 
  try{ 

    int bytesRead = socket.read(input); 

    ...... 

    //激活线程池 处理这些request 
    requestHandle(new Request(socket,btt)); 

    ..... 


  }catch(Exception e) { 
  } 

} 

 

注意在Handler里面又执行了一次attach,这样,覆盖前面的Acceptor,下次该Handler又有READ事件发生时,将直接触发Handler.从而开始了数据的读 处理 写 发出等流程处理。

将数据读出后,可以将这些数据处理线程做成一个线程池,这样,数据读出后,立即扔到线程池中,这样加速处理速度:



 

更进一步,我们可以使用多个Selector分别处理连接和读事件。

一个高性能的Java网络服务机制就要形成,激动人心的集群并行计算即将实现。

 

  • 大小: 71.1 KB
  • 大小: 68 KB
  • 大小: 76.9 KB
  • 大小: 125.3 KB
分享到:
评论
1 楼 luciferdevil 2011-07-27  
这个例子有问题

相关推荐

    Reactor模式和NIO

    Reactor模式和NIO是两种在网络编程中广泛使用的并发处理技术。Reactor模式是一种事件驱动的设计模式,主要用于解决高并发场景下的系统设计问题,而Java的NIO(Non-blocking Input/Output,非阻塞I/O)是Java平台提供...

    socket-nio-single-reactor.zip

    本示例代码旨在帮助开发者理解如何使用Java NIO和Reactor模式构建网络服务。尽管测试代码可能不完全准确,但它能展示基本的原理和工作流程。 首先,我们要了解什么是Reactor模式。Reactor模式是一种事件驱动的设计...

    Observer and Reactor 观察者和recator的比较

    Observer和Reactor模式虽然都是处理事件和状态变化,但它们在实际应用中有各自的优势和适用场景。Observer更适用于需要实时同步更新的场景,而Reactor更适合于需要高效处理并发事件的系统,尤其是在实时系统和嵌入式...

    ScalableIOJava(NIO如何实现Selector模式的).pdf

    标题《Scalable IO in Java》和描述表明本文档讨论...通过理解Reactor模式以及如何在Java中通过NIO API实现这一模式,开发者可以构建出能够处理大量并发连接的应用程序,并达到高可伸缩性、高可用性以及高性能的目标。

    基于Java NIO反应器模式设计与实现

    在反应器模式的Java实现中,一个Reactor(反应器)负责监听和分发事件,它持续监测一个或多个输入源,一旦有事件发生,它就将事件分发给相应的处理器进行处理。处理器(Handler)定义了事件处理的方法,每个处理器...

    bio-nio-aio.zip

    总结,Java IO的发展经历了从BIO到NIO的转变,再到Reactor模式的优化,每一步都是为了提高系统的并发处理能力和资源利用率。理解并熟练掌握这些IO模型,对于开发高效、稳定的服务器端程序至关重要。通过对压缩包中的...

    Reactor Pattern (一)

    在Java中,NIO(Non-blocking I/O)框架就是Reactor模式的一个典型应用,它允许一个线程处理多个通道(Channel)上的I/O事件,而不是为每个连接创建一个单独的线程。NIO中的Selector组件就是Reactor的核心,它能够...

    深入浅出NIO

    3. **Reactor模式**:在NIO中,Reactor模式是一种处理多个客户端连接的并发设计模式。它通过一个线程来监听和接受新的连接,然后分派事件到相应的处理器。相比于传统的多线程模型,Reactor模式可以更有效地管理大量...

    netty 入门Reactor示例

    在Java中,NIO(非阻塞I/O)库为实现Reactor模式提供了基础。Netty基于NIO,并在其之上构建了一套高效且易用的网络编程框架。 Netty中的Reactor分为两个主要部分:主线程(BossGroup)和工作线程(WorkerGroup)。...

    java NIO socket聊天室

    可以作为NIO socket入门的例子,Reactor模式,重点理解key.attach, jar文件里包含了源代码 1,运行server.bat启动服务器,可以打开编辑,修改端口号 2,运行client.bat启动客户端,可以打开编辑,ip,和端口号 3...

    Java NIO原理和使用

    本文主要简单介绍NIO的基本原理,在下一篇文章中,将结合Reactor模式和著名线程大师Doug Lea的一篇文章深入讨论。 NIO主要原理和适用。 NIO 有一个主要的类Selector,这个类似一个观察者,只要我们把需要探知的...

    redis源码阅读笔记(10)——事件

    在Redis源码阅读笔记(10)——事件中,我们将探讨Redis如何利用事件模型来实现非阻塞I/O,以及相关的编程模型如Reactor模式和NIO。 Redis使用了一个基于epoll的事件处理器,epoll是Linux系统提供的一种高效I/O多路...

    基于NIO的群聊.zip

    - Reactor模式是一种事件驱动的设计模式,用于处理多个并发输入请求。在这个群聊项目中,Reactor采用单线程模型,意味着所有事件(如新的连接、读写事件)都在同一个线程中处理,这简化了同步问题,但可能限制了...

    reactor:NIO 编程模型 - Reactor,各版本实现

    依据 Doug Lea 的 基于 NIO 实现的 Reacotr 模式的回显服务器 BasicHandler: 单线程处理器 MultiReactor: 主从 Reactor MultithreadHandler: 线程池处理器 Reactor: 接收连接,I/O 读写 Reactor 模型的说明: ...

    基于Java NIO的网络编程框架.zip

    本项目深入探讨了Java网络编程中的多种模式,包括BIO(阻塞IO)、NIO(非阻塞IO)、IO多路复用(select、poll、epoll)、Reactor模式,以及零拷贝技术。通过这些实现,项目展示了如何在高并发环境下优化网络通信效率...

    Java NIO核心概念总结篇

    与传统的阻塞 I/O 相比,NIO 的设计思想更为先进,它采用了 Reactor 模式的事件驱动机制来实现非阻塞 I/O。通过这种方式,Java NIO 能够显著提升 I/O 性能,并且在某些场景下的性能甚至可以与 C 语言媲美。 **...

    NIO trick and trap NIO网络

    - **Reactor模式**:这是一种常见的设计模式,用于实现NIO网络框架。它包含以下核心组件: - **SynchronousEventDemultiplexer**:负责事件循环和事件分离。 - **Dispatcher**:事件派发器,负责将事件分发给对应...

    java nio 原理浅析

    Netty默认使用Reactor模式的变种,即单个Boss线程和多个Worker线程的配置。 1. **网络模型**: - **单Reactor单线程模型**:所有工作包括接受新连接、处理I/O事件和调用处理器都在同一个线程中进行,适用于简单且...

    Java NIO与IO性能对比分析.pdf

    Java NIO的Reactor模式是实现高并发的关键。Reactor模式是一种事件驱动的架构模式,它具有事件分离器、事件处理器以及复用的事件队列。事件分离器负责监听事件的发生,事件处理器对相应的事件做出响应。在Java NIO中...

Global site tag (gtag.js) - Google Analytics