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

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开发一个高性能聊天系统

Socket打造高性能服务器

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

并发模型

EDA

分享到:
评论

相关推荐

    昆仑通态控温程序,MCGS通讯10块仪表,不需要用plc,直接触摸屏通讯各种仪表

    昆仑通态控温程序,MCGS通讯10块仪表,不需要用plc,直接触摸屏通讯各种仪表

    基于三菱fxPLC和组态王燃油锅炉控制系统 带解释的梯形图程序,接线图原理图图纸,io分配,组态画面

    基于三菱fxPLC和组态王燃油锅炉控制系统 带解释的梯形图程序,接线图原理图图纸,io分配,组态画面

    基于SpringBoot+Vue的助农电商平台(编号:4114842).zip

    基于SpringBoot+Vue的助农电商平台(编号:4114842).zip

    【岗位说明】销售部销售岗位说明书.doc

    【岗位说明】销售部销售岗位说明书

    幼儿园儿童成长手册记录卡模板.pptx

    幼儿园儿童成长手册记录卡模板

    计算机数据表示实验(HUST)

    本实训将帮助同学们巩固对计算机中数据表示方法的理解,要求能设计汉字国标码与区位码之间的转换电路,能批量获取汉字机内码并用点阵形式进行显示。通过设计 16 位数据的海明编解码电路,16 位数据的 CRC 并行编解码电路,帮助同学们理解校验码传输过程。通过校验码流水传输实验帮助大家提前建立流水线的基本概念。 第1关汉字国标码转区位码实验 第2关汉字机内码获取实验 第3关偶校验编码设计 第4关偶校验解码电路设计 第5关16位海明编码电路设计 第6关16位海明解码电路设计 第7关海明编码流水传输实验 第8关16位CRC并行编解码电路设计 第9关CRC编码流水传输实验。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    【岗位说明】销售部各职务详细岗位说明书描述.doc

    【岗位说明】销售部各职务详细岗位说明书描述

    机械设计铜柱胶壳铁片组装机sw16可编辑非常好的设计图纸100%好用.zip

    机械设计铜柱胶壳铁片组装机sw16可编辑非常好的设计图纸100%好用.zip

    C# API大全及C#如何调用API

    C# API大全,讲述C#如何调用API。

    postgis-2.4.0.tar.gz

    postgis-2.4.0.tar.gz,postgis安装包。 PostGIS 在对象关系型数据库 PostgreSQL 上增加了存储管理空间数据的能力,相当于 Oracle 的 spatial 部分。PostGIS 最大的特点是符合并且实现了 OpenGIS 的一些规范,是最著名的开源 GIS 数据库。

    从小说中提取对话数据集.zip

    从小说中提取对话数据集摘录对话本仓库只为huanhuan-chat泛化版的一部分内容(文本对话抽取),欢迎大家给huanhuan-chat仓库star!本仓库的最大贡献就是为泛化的Character AI提供了从小说中建立数据集的功能。huanhuan-chat: https://github.com/KMnO4-zx/huanhuan-chat.git展示repohttps://github.com/KMnO4-zx/extract-dialogue.git本项目利用chatgpt从小说中提取对话集,提取的样本中包括role,dialogue,比如以下的形式{ "role": "艾伦", "dialogue": "不,不要提,这真是太倒霉了!我从楼梯上摔了下去,出现了较为严重的骨裂,只能打石膏做固定。"}{ "role": "克莱恩", "dialogue": "真是不够走运啊。"}快速入门克隆仓库并切换目录git clone https://github.com/KMnO4-zx/extract-dialogue

    【Python】基于Python的用于爬取gitlab上的数据的python项目_pgj.zip

    【Python】基于Python的用于爬取gitlab上的数据的python项目_pgj

    基于java+springboot+vue+mysql的茶叶商城系统 源码+数据库+论文(高分毕业设计).zip

    项目已获导师指导并通过的高分毕业设计项目,可作为课程设计和期末大作业,下载即用无需修改,项目完整确保可以运行。 包含:项目源码、数据库脚本、软件工具等,该项目可以作为毕设、课程设计使用,前后端代码都在里面。 该系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值。 项目都经过严格调试,确保可以运行!可以放心下载 技术组成 语言:java 开发环境:idea 数据库:MySql5.7以上 部署环境:maven 数据库工具:navicat

    数模国赛模板.zip,个人学习整理,仅供参考

    《数模国赛模板》是一个压缩包文件,通常包含了参与全国数学建模竞赛(以下简称“数模国赛”)所需的各类资源和模板。这个压缩包可能是为了帮助参赛者准备比赛而设计的,里面可能涵盖了论文写作、模型构建、数据处理等方面的内容。下面,我们将详细探讨这些潜在的知识点。 1. **论文结构与格式**: 数模国赛的论文一般包括摘要、引言、模型建立、模型求解、模型检验、模型应用、结论和参考文献等部分。模板可能提供每个部分的标准格式和写作指导,帮助参赛者规范论文结构。 2. **数学建模基础**: 建模是数模比赛的核心,涉及线性代数、微积分、概率统计、优化理论等数学工具。模板可能包含各种常见问题的建模思路,以及如何运用这些数学知识解决实际问题。 3. **数据分析方法**: 数据处理是建模过程中必不可少的一环,可能涉及到数据清洗、数据可视化、回归分析、时间序列分析、聚类分析等。模板会提供数据分析的基本步骤和常用软件(如Excel、SPSS、R或Python)的使用教程。 4. **编程技能**: 在数模比赛中,。内容来源于网络分享,如有侵权请联系我删除。另外如果没有积分的同学需要下载,请私信我。

    【Android】一个Android端的蓝牙遥控APP,提供Arduino库,方便用于机器人、小车等调试用途_pgj.zip

    【Android】一个Android端的蓝牙遥控APP,提供Arduino库,方便用于机器人、小车等调试用途_pgj

    机械设计快走丝电火花线切割机床(毕设ug8+cad+说明书)非常好的设计图纸100%好用.zip

    机械设计快走丝电火花线切割机床(毕设ug8+cad+说明书)非常好的设计图纸100%好用.zip

    开放旋转机械故障数据集(旋转机械开源故障数据集整理).zip

    路线图1.简介2.美国-凯斯西储大学轴承数据中心轴承数据集3.美国-机械故障预防技术学会MFPT4.德国-帕德伯恩大学Paderborn轴承数据集5.法国-FEMTO-ST轴承数据集6.美国-辛辛那提大学IMS轴承劳工数据集7.美国-康涅狄格大学康涅狄格大学齿轮数据集8.中国-西安交通大学轴承加速租赁数据集XJTU-SY Bearing Datasets9.中国-东南大学齿轮箱数据集10.声学与振动数据库(振动与声学数据库)11.机械故障设备诊断数据集及技术资料大全12.美国-宇航局预测数据存储库-CoE Datasets13.中国-第三届工业大数据创新竞赛旋转机械数据集14.加拿大-渥太华大学轴承数据集15.意大利-都灵理工大学轴承数据DIRG BearingData16.巴西-里约热内卢联邦大学MAFAULDA轴承数据集17.中国-武汉大学-转子数据18.中国电机振动数据(七月在线竞赛)19.中国-轴承数据集(DC竞赛)20.中国-上海交通大学轴承数据集旋转机械故障数据集打开旋转机械故障数据集1.简介华丽,现在做机械故障研究最基础

    基于自定义实现的Transformer模型的英汉翻译任务训练得到的模型参数权重字典

    对应的模型的超参数: d_model = 512 d_ff = 2048 n_layers = 6 n_heads = 8 dropout_p=0.1 src_vocab_size = 4456 trg_vocab_size = 8013

    机械设计手控涂布机sw20可编辑非常好的设计图纸100%好用.zip

    机械设计手控涂布机sw20可编辑非常好的设计图纸100%好用.zip

    开源物联网平台 - 物联网解决方案的设备管理,数据收集,处理.zip

    Groza - 开源物联网平台 目录特性原理安装使用帮助授权特性

Global site tag (gtag.js) - Google Analytics