Nio学习3——基础模型:Reactor模式和多路复用

Reactor模式和NIO

本文可看成是对Doug Lea Scalable IO in Java一文的翻译。

当前分布式计算 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网络服务机制就要形成,激动人心的集群并行计算即将实现。

Scalable IO in Java原文

NIO原理与应用

用NIO开发一个高性能聊天系统

Socket打造高性能服务器

更多NIO专题系列讨论....

服务器后端性能大比拼

事件驱动编程

并发模型

Rx (Reactive Extensions)介绍

Reactive编程

EDA

2002年大神地址:http://www.jdon.com/concurrent/reactor.htm

Nio学习3——基础模型:Reactor模式和多路复用,布布扣,bubuko.com

时间: 2024-08-18 11:11:09

Nio学习3——基础模型:Reactor模式和多路复用的相关文章

Nio学习3——基础模型:多路复用模型

Reactor模式和NIO 本文可看成是对Doug Lea Scalable IO in Java一文的翻译. 当前分布式计算 Web Services盛行天下,这些网络服务的底层都离不开对socket的操作.他们都有一个共同的结构: 1. Read request 2. Decode request 3. Process service 4. Encode reply 5. Send reply 经典的网络服务的设计例如以下图,在每一个线程中完毕对数据的处理: 但这样的模式在用户负载添加时,性

muduo网络库学习笔记(9):Reactor模式的关键结构

Reactor模式简介 Reactor的意思是"反应堆",是一种事件驱动机制.它和普通函数调用的不同之处在于:应用程序不是主动的调用某个API完成处理,而是恰恰相反,Reactor逆置了事件处理流程,应用程序需要提供相应的接口并注册到Reactor上,如果相应的时间发生,Reactor将主动调用应用程序注册的接口,这些接口又称为"回调函数". moduo库Reactor模式的实现 muduo中Reactor的关键结构包括:EventLoop.Poller和Chann

Nio学习5——对NIO.2(AIO) Reactor模式封装的拆解

我们通过nio学习了Reactor模式,但是在java7中又出现了NIO.2,新的异步框架出来了,在上节中的服务端视线中看不到Reactor的影子了,但是Netty in action中写到:But notice that NIO.2 handles threading and the creation of the so-called event loop for you.所以模式还是没变,只是封装了而已!那让我们来分解下AIO(NIO.2)的封装吧! 首先看下AsynchronousServ

reactor模式与java nio

?? Reactor是由Schmidt, Douglas C提出的一种模式,在高并发server实现中广泛採用. 改模式採用事件驱动方式,当事件出现时,后调用对应的事件处理代码(Event Handler). 这个模式是高并发server的基础.如nginx和lighttpd. 这两种对大并发,但每一个请求处理都非常快的场景非常适合. 通常的web訪问就是这个特点. 结构 包含了5个部分,当中handle和Synchronous Event Demultiplexer有OS实现. Handles

Java NIO学习系列五:I/O模型

前面总结了很多IO.NIO相关的基础知识点,还总结了IO和NIO之间的区别及各自适用场景,本文会从另一个视角来学习一下IO,即IO模型.什么是IO模型?对于不同人.在不同场景下给出的答案是不同的,所以先限定一下本文的上下文:Linux环境下的network IO. 本文会从如下几个方面展开: 一些基础概念 I/O模型 总结 1. 一些基础概念 IO模型这个概念属于比较基础的底层概念,在此之前容我再先简单介绍一些涉及到的更底层的概念,帮助对I/O模型的理解: 1.1 用户空间与内核空间 现在操作系

NIO Reactor模式

Reactor模式和NIO——转: 本文可看成是对Doug Lea Scalable IO in Java一文的翻译. 当前分布式计算 Web Services盛行天下,这些网络服务的底层都离不开对socket的操作. 他们都有一个共同的结构:1. Read request2. Decode request3. Process service4. Encode reply5. Send reply 经典的网络服务的设计如下图,在每个线程中完成对数据的处理: 但这种模式在用户负载增加时,性能将下降

java NIO的多路复用及reactor模式【转载】

本文转载自:http://www.blogjava.net/hello-yun/archive/2012/10/17/389729.html java nio从1.4版本就出现了,而且依它优异的性能赢得了广大java开发爱好者的信赖.我很纳闷,为啥我到现在才接触,难道我不是爱好者,难道nio不优秀.经过长达半分钟的思考,我意识到:时候未到.以前总是写那些老掉牙的web程序,唉,好不容易翻身啦,现在心里好受多了.因为真不想自己到了30岁,还在说,我会ssh,会ssi,精通javascript,精通

Java进阶知识点5:服务端高并发的基石 - NIO与Reactor模式以及AIO与Proactor模式

一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等. 一般来说,系统架构的合理程度,决定了系统在整体性能上的伸缩性(高伸缩性,简而言之就是可以很任性,性能不行就加机器,加到性能足够为止):而单节点在性能上的优化程度,决定了单个请求的时延,以及要达到期望的性能,所需集群规模的大小.两者双管齐下,才能快速构建出性能良好的系统. 今天,我们就聊聊在单节点

两种高效的事件处理模型:Reactor模式和Proactor模式

随着IO多路复用技术的出现,出现了很多事件处理模式.同步I/O模型通常由Reactor模式实现,而异步I/O模型则由Proactor模式实现. Reactor模式: Reator类图如上所示,Reactor模式又叫反应器或反应堆,即实现注册描述符(Handle)及事件的处理器(EventHandler),当有事件发生的时候,事件多路分发器(Event Demultiplexer)做出反应,调用事件具体的处理函数(ConcreteEventHandler::handle_event()). Rea