当前分布式计算 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模式代码:

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.util.Iterator;
import java.util.Set;/*** 反应器模式 用于解决多用户访问并发问题* * 举个例子:餐厅服务问题* * 传统线程池做法:来一个客人(请求)去一个服务员(线程)* 反应器模式做法:当客人点菜的时候,服务员就可以去招呼其他客人了,等客人点好了菜,直接招呼一声:服务员* * @author linxcool*/
public class Reactor implements Runnable {public final Selector selector;public final ServerSocketChannel serverSocketChannel;public Reactor(int port) throws IOException {selector = Selector.open();serverSocketChannel = ServerSocketChannel.open();InetSocketAddress inetSocketAddress = new InetSocketAddress(InetAddress.getLocalHost(), port);serverSocketChannel.socket().bind(inetSocketAddress);serverSocketChannel.configureBlocking(false);// 向selector注册该channelSelectionKey selectionKey = serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);// 利用selectionKey的attache功能绑定Acceptor 如果有事情,触发AcceptorselectionKey.attach(new Acceptor(this));}@Overridepublic void run() {try {while (!Thread.interrupted()) {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> it = selectionKeys.iterator();// Selector如果发现channel有OP_ACCEPT或READ事件发生,下列遍历就会进行。while (it.hasNext()) {// 来一个事件 第一次触发一个accepter线程// 以后触发SocketReadHandlerSelectionKey selectionKey = it.next();dispatch(selectionKey);selectionKeys.clear();}}} catch (IOException e) {e.printStackTrace();}}/*** 运行Acceptor或SocketReadHandler* * @param key*/void dispatch(SelectionKey key) {Runnable r = (Runnable) (key.attachment());if (r != null) {r.run();}}}

import java.io.IOException;
import java.nio.channels.SocketChannel;public class Acceptor implements Runnable {private Reactor reactor;public Acceptor(Reactor reactor) {this.reactor = reactor;}@Overridepublic void run() {try {SocketChannel socketChannel = reactor.serverSocketChannel.accept();if (socketChannel != null)// 调用Handler来处理channelnew SocketReadHandler(reactor.selector, socketChannel);} catch (IOException e) {e.printStackTrace();}}
}

public class SocketReadHandler implements Runnable {private SocketChannel socketChannel;public SocketReadHandler(Selector selector, SocketChannel socketChannel)throws IOException {this.socketChannel = socketChannel;socketChannel.configureBlocking(false);SelectionKey selectionKey = socketChannel.register(selector, 0);// 将SelectionKey绑定为本Handler 下一步有事件触发时,将调用本类的run方法。// 参看dispatch(SelectionKey key)selectionKey.attach(this);// 同时将SelectionKey标记为可读,以便读取。
        selectionKey.interestOps(SelectionKey.OP_READ);selector.wakeup();}/*** 处理读取数据*/@Overridepublic void run() {ByteBuffer inputBuffer = ByteBuffer.allocate(1024);inputBuffer.clear();try {socketChannel.read(inputBuffer);// 激活线程池 处理这些request// requestHandle(new Request(socket,btt));} catch (IOException e) {e.printStackTrace();}}
}

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

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

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

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

转载于:https://www.cnblogs.com/leeeee/p/7276463.html

Reactor模式和NIO相关推荐

  1. Reactor模式与NIO

    文章目录 Reactor模式与NIO 简单的NIO编程方式 Reactor模式 单线程Reactor模式 多线程Reactor模式 主从Reactor多线程模型 Reactor模式与NIO NIO是非 ...

  2. java NIO和Reactor模式

    Reactor模式和NIO 板桥里人 jdon.com 2002/11/08 本文可看成是对Doug Lea Scalable IO in Java一文的翻译. 当前分布式计算 Web Service ...

  3. 什么是 Reactor 模式?

    什么是 Reactor 模式? 融入 NIO 技术的 Reactor 模式   Reactor 模式并不是什么很神秘的东西.一般来说,通信有以下两个关键步骤:一是建立连接,二是进行数据的传输.一般对通 ...

  4. 【Netty】Netty 简介 ( 原生 NIO 弊端 | Netty 框架 | Netty 版本 | 线程模型 | 线程 阻塞 IO 模型 | Reactor 模式引入 )

    文章目录 一. NIO 原生 API 弊端 二. Netty 简介 三. Netty 架构 四. Netty 版本 五. Netty 线程模型 六. 阻塞 IO 线程模型 七. 反应器 ( React ...

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

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

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

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

  7. java reactor模式例子_JAVA BIO,NIO,Reactor模式总结

    传统同步阻塞I/O(BIO) 在NIO之前编写服务器使用的是同步阻塞I/O(Blocking I/O).下面是一个典型的线程池客服端服务器示例代码,这段代码在连接数急剧上升的情况下,这个服务器代码就会 ...

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

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

  9. Reactor模式与Proactor模式

    博主一脚刚踏进分布式的大门(看<分布式Java应用>,如果大家有啥推荐的书欢迎留言~),发现书中对NIO采用的Reactor模式.AIO采用的Proactor模式一笔带过,好奇心趋势我找了 ...

最新文章

  1. 嵌入式自学多久可以找工作?应届生找嵌入式工作难吗?
  2. 软件项目随着数据量的不断增加,有什么优化方案么?
  3. 赫夫曼树建立c语言源程序编译结果详细解释,c语言构建哈夫曼树(附运行结果图)[本站推荐]...
  4. Python脚本解密RSA加密密码
  5. 一个比较完美的spacer div技巧
  6. 图论解决复杂路口红绿灯安排,python语言实现
  7. 16款测序平台性能大PK,华大表现不俗!基于人类和细菌基因组DNA水平的多平台测序数据研究成果发布...
  8. 数据存储与传输---编码与解码---硬盘和内存要分清!
  9. 一根绳子从一头烧需30时分钟_小学生一分钟跳绳满分训练指南
  10. [转载] python中append和extend函数区别
  11. 计算机月考分析报告,月考成绩分析总结与反思范文5篇
  12. 【读书笔记】《JS函数式编程指南》(一)
  13. 蓝牙耳机哪个品牌最好?数码博主整理2023超高性价比蓝牙耳机推荐
  14. 金山中学 rugular SRM 04 ——纪念我的第一次Ak
  15. 我觉得是全网最全最好最有用的sed命令详解+示例
  16. 洛谷P4711 【化学】 相对分子质量 简单题解
  17. Kali linux渗透测试系列————34、Kali linux 维持访问之创建Web后门
  18. python爬取网页内容post_python爬虫之使用POST抓取网页内容
  19. 【指数编制系列二】数据标准化方法
  20. Django 【全家桶】

热门文章

  1. R语言与数据挖掘学习笔记(常用的包)
  2. linux 调整shmmax,科学网—Ubuntu 9.10 中更改 linux kernal 中的shmmax大小 - 孙鹏的博文...
  3. 目标检测(三)--DPM
  4. 系统学习深度学习(九)--激活函数总结
  5. 图像融合(四)-- 对比度金字塔
  6. 用python提取图片主要颜色_用Python提取图片主要颜色
  7. python回调类_python 回调函数和回调方法的实现分析
  8. “21天好习惯”第一期-9
  9. 【数据库原理实验(openGauss)】创建数据库、表和索引
  10. git status命令