Reactor与NIO

1. Reactor的由来

Reactor是一种广泛应用在服务器端开发的设计模式。Reactor中文大多译为“反应堆”,我当初接触这个概念的时候,就感觉很厉害,是不是它的原理就跟“核反应”差不多?后来才知道其实没有什么关系,从Reactor的兄弟“Proactor”(多译为前摄器)就能看得出来,这两个词的中文翻译其实都不是太好,不够形象。实际上,Reactor模式又有别名“Dispatcher”或者“Notifier”,我觉得这两个都更加能表明它的本质。

那么,Reactor模式究竟是个什么东西呢?这要从事件驱动的开发方式说起。我们知道,对于应用服务器,一个主要规律就是,CPU的处理速度是要远远快于IO速度的,如果CPU为了IO操作(例如从Socket读取一段数据)而阻塞显然是不划算的。好一点的方法是分为多进程或者线程去进行处理,但是这样会带来一些进程切换的开销,试想一个进程一个数据读500ms,期间进程切换到它3次,但是CPU却什么都不能干,就这么切换走了,是不是也不划算?

这时先驱们找到了事件驱动,或者叫回调的方式,来完成这件事情。这种方式就是,应用业务向一个中间人注册一个回调(event handler),当IO就绪后,这个中间人产生一个事件,并通知handler进行处理。这种回调的方式,也体现了“好莱坞原则”——“Don‘t call us,we‘ll call you”。

好了,我们现在来看Reactor模式。在前面事件驱动的例子里有个问题:我们如何知道IO就绪就个事件,谁来充当这个中间人?Reactor模式的答案是:由一个不断等待和循环的单独进程(线程)来做这件事,它接受所有handler的注册,并负责先操作系统查询IO是否就绪,在就绪后就调用指定handler进行处理,这个角色的名字就叫做Reactor。

2. Reactor与NIO

Java中的NIO可以很好的和Reactor模式结合。关于NIO中的Reactor模式,我想没有什么资料能比Doug Lea大神(不知道Doug Lea?看看JDK集合包和并发包的作者吧)在《Scalable IO in Java》解释的更简洁和全面了。NIO中Reactor的核心是Selector,我写了一个简单的Reactor示例,注意这里有一个核心的Reactor的循环(这种循环结构又叫做EventLoop):

package us.codecraft.netty.reactor;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class Handler implements Runnable {
    final SocketChannel socket = null;
    final SelectionKey sk;
    Handler(Selector sel) throws IOException{
        socket.configureBlocking(false);
        sk = socket.register(sel,0);
        sk.attach(this);
        sk.interestOps(SelectionKey.OP_READ);
        sel.wakeup();
    }
    @Override
    public void run(){
        //TODO:处理逻辑
    }
}
package us.codecraft.netty.reactor;
import java.io.IOException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.util.Iterator;
import java.util.Set;

public class Reactor implements Runnable{
    Selector selector;
    public Reactor() throws IOException {
        selector = Selector.open();
    }
    public void run(){
        try{
            while(!Thread.interrupted()){
                //循环,等待事件
                selector.select();
                Set selected = selector.selectedKeys();
                Interator it = selected.iterator();
                while(it.hasNext())
                    //调用handler,处理事件
                    dispatch((SelectionKey)(it.next()));
                selected.clear();
            }
        }catch(IOException ex){
        }
    }
    void dispatch(SelectionKey k) {
        Runnable r = (Runnable) (k.attachment());
        if(r != null) r.run();
    }
}
package us.codecraft.netty.reactor;
import java.io.IOException;
public class Main{
    public static void main(String[] args) throws IOException {
        Reactor  reactor = new Reactor();
        new Handler(reactor.selector);
        reactor.run();
    }
}
时间: 2024-11-21 00:05:51

Reactor与NIO的相关文章

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 经典的网络服务的设计如下图,在每个线程中完成对数据的处理: 但这种模式在用户负载增加时,性能将下降

【转】Netty那点事(四)Netty与Reactor模式

[原文]https://github.com/code4craft/netty-learning/blob/master/posts/ch4-reactor.md 一:Netty.NIO.多线程? 时隔很久终于又更新了!之前一直迟迟未动也是因为积累不够,后面比较难下手.过年期间@李林锋hw发布了一个Netty5.0架构剖析和源码解读 http://vdisk.weibo.com/s/C9LV9iVqH13rW/1391437855,看完也是收获不少.前面的文章我们分析了Netty的结构,这次咱们

Netty、NIO、多线程

一:Netty.NIO.多线程? 时隔很久终于又更新了!之前一直迟迟未动也是因为积累不够,后面比较难下手.过年期间@李林锋hw发布了一个Netty5.0架构剖析和源码解读,看完也是收获不少.前面的文章我们分析了Netty的结构,这次咱们来分析最错综复杂的一部分-Netty中的多线程以及NIO的应用. 理清NIO与Netty的关系之前,我们必须先要来看看Reactor模式.Netty是一个典型的多线程的Reactor模式的使用,理解了这部分,在宏观上理解Netty的NIO及多线程部分就不会有什么困

IO模型介绍 以及同步异步阻塞非阻塞的区别

阻塞:用户进程访问数据时,如果未完成IO,等待IO操作完成或者进行系统调用来判断IO是否完成非阻塞:用户进程访问数据时,会马上返回一个状态值,无论是否完成 同步:用户进程发起IO(就绪判断)后,轮询内核状态异步:用户进程发起IO后,可以做其他事情,等待内核通知 介绍一下IO模型 网络IO模型和文件IO模型是一样的,上图是IO的5种模型,包括阻塞IO.非阻塞IO.多路复用IO.信号驱动的IO.异步IO. 一次IO包括两个过程,内核数据准备 .把数据从内核空间copy到用户空间. 1.阻塞IO(re

常见面试问题总结

[Java] 1. 容器 1)队列(queue): 若Blocking:阻塞put/take  offer/peek poll 异常element/remove a. PriorityQueue:comparator  堆排序 b. Deque:双向队列  linkedList  addFirst() c. DelayQueue:类似timeTask,延迟期满才能提取元素 d. ConcurrentLinkedQueue:线程安全 2)数组(Array):注意左右边界校验,如arr!=null&

NIO Reactor模式

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

NIO和Reactor

本文参考Doug Lea的Scalable IO in Java. 网络服务 随着网络服务的越来越多,我们对网络服务的性能有了更高的要求,提供一个高性能,稳定的web服务是一件很麻烦的事情,所以有了netty框架帮我们完成. 我们对各种各样的网络服务进行抽象,得到最基本的业务流程: 1:读取请求信息 2:对请求信息进行解码 3:进行相关的业务处理 4:对处理结果进行编码 5:发送请求 看到这,netty的ChannelHandler就是干这几件事情的. 传统的网络服务 在jdk1.4之前,我们只

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