Reactor模式和NIO

板桥里人 jdon.com 2002/11/08

本文可看成是对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注册该channelSelectionKey sk =serverSocket.register(selector,SelectionKey.OP_ACCEPT);logger.debug("-->Start serverSocket.register!");//利用sk的attache功能绑定Acceptor 如果有事情,触发Acceptorsk.attach(new Acceptor());logger.debug("-->attach(new Acceptor()!");}public void run() { // normally in a new Threadtry {while (!Thread.interrupted()){selector.select();Set selected = selector.selectedKeys();Iterator it = selected.iterator();//Selector如果发现channel有OP_ACCEPT或READ事件发生,下列遍历就会进行。while (it.hasNext())//来一个事件 第一次触发一个accepter线程//以后触发SocketReadHandlerdispatch((SelectionKey)(it.next()));selected.clear();}}catch (IOException ex) {logger.debug("reactor stop!"+ex);}}//运行Acceptor或SocketReadHandlervoid dispatch(SelectionKey k) {Runnable r = (Runnable)(k.attachment());if (r != null){// r.run();}}class Acceptor implements Runnable { // innerpublic void run() {try {logger.debug("-->ready for accept!");SocketChannel c = serverSocket.accept();if (c != null)//调用Handler来处理channelnew 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);......//激活线程池 处理这些requestrequestHandle(new Request(socket,btt));.....}catch(Exception e) {}}

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

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

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

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

java NIO和Reactor模式相关推荐

  1. Java进阶(五)Java I/O模型从BIO到NIO和Reactor模式

    本文介绍了Java中的四种I/O模型,同步阻塞,同步非阻塞,多路复用,异步阻塞.同时将NIO和BIO进行了对比,并详细分析了基于NIO的Reactor模式,包括经典单线程模型以及多线程模式和多Reac ...

  2. Java I/O模型从BIO到NIO和Reactor模式

    本文转发自技术世界,原文链接 http://www.jasongj.com/java/nio_reactor/ 一.Java I/O模型 同步 vs. 异步 同步I/O 每个请求必须逐个地被处理,一个 ...

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

    一.背景 要提升服务器的并发处理能力,通常有两大方向的思路. 1.系统架构层面.比如负载均衡.多级缓存.单元化部署等等. 2.单节点优化层面.比如修复代码级别的性能Bug.JVM参数调优.IO优化等等 ...

  4. java nio doug_深入的聊聊 Java NIO

    趁着三天假期,把Java NIO和Reactor模式整理总结了下,文章特别细节的知识点没有写,如一些API的具体实现.类似数据读到Buffer后再写出时,为什么需要复位操作,这些都属于NIO基础知识, ...

  5. Reactor模式和NIO

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

  6. 高性能IO之Reactor模式

    讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty.Redis在使用的IO模式,为什么需要这种模式,它是如何设计来解决高性能并发的呢? 最最原始的网络编程思路就是服务器用一个w ...

  7. 高性能实践IO之Reactor模式

    讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty.Redis在使用的IO模式,为什么需要这种模式,它是如何设计来解决高性能并发的呢? 最最原始的网络编程思路就是服务器用一个w ...

  8. 设计模式:高性能IO之Reactor模式

    讲到高性能IO绕不开Reactor模式,它是大多数IO相关组件如Netty.Redis在使用的IO模式,为什么需要这种模式,它是如何设计来解决高性能并发的呢? 最最原始的网络编程思路就是服务器用一个w ...

  9. 【RPC】I/O模型——BIO、NIO、AIO及NIO的Rector模式

    文章目录 1. I/O模型 1.1 用户进程与系统进程 1.2 一次I/O操作经历了什么? 1.3 I/O模型是什么? 2. Java对I/O模型的封装 2.1 BIO 2.2 NIO 2.3 NIO ...

最新文章

  1. MySQL基础之select基本查询
  2. 脑出血遇到深度学习,是否可以无所遁形?
  3. python 逻辑回归
  4. c语言对齐方式研究笔记
  5. python 从字符串中随机选取4个字符_我需要一个Python函数,当给定字符的期望概率时,它将输出4个不同字符的随机字符串...
  6. git clone github_GitHub为什么连接缓慢以及解决方法
  7. python 精度损失_Python的浮点数损失精度问题
  8. 关于跨域获取cookie问题的解决
  9. apk破解工具介绍与使用
  10. 关于maven项目中的Missing artifact *.jar ...
  11. python实现app自动签到器_python实现网页自动签到功能
  12. 服务器无线桥接怎么设置,路由器怎么设置桥接方法 2个路由器无线桥接设置图解...
  13. Torch和torchvision的安装
  14. 1.2 网络爬虫分类
  15. BGP简介-如何配置 EBGP(外部 BGP)
  16. 赵小楼《天道》《遥远的救世主》深度解析(44)怎么理解肖亚文听到芮小丹说爱上丁元英时所说的“地狱”?
  17. 《Python3》读书笔记(上)
  18. COMSOL本周六开课/FDTD时域有限差分/RSoft光电器件仿真设计专题线上通知
  19. API Store使用步骤
  20. gimbal lock 视频解释

热门文章

  1. Apache优化——日志管理
  2. 拥抱.NET Core系列:Logging (1)
  3. 前端常用linux命令
  4. django from组件 实现增加 删除 编辑(推荐用法)
  5. IP网络设计系列之-局域网设计
  6. Mybatis源码: Builder Mapper Executor
  7. jqGrid getGridParam办法
  8. 如何打包和部署air应用程序
  9. struts2从一个action跳到另一个action的配置方法
  10. 正则基础之 NFA引擎匹配原理