`
xinklabi
  • 浏览: 1579440 次
  • 性别: Icon_minigender_1
  • 来自: 吉林
文章分类
社区版块
存档分类
最新评论

网络编程高性能IO:Reactor和Proactor介绍

 
阅读更多

1、标准定义

两种I/O多路复用模式:Reactor和Proactor

一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事件源的I/O事件分离出来,并分发到对应的read/write事件处理器(Event Handler)。开发人员预先注册需要处理的事件及其

转自:http://www.cnblogs.com/dawen/archive/2011/05/18/2050358.html

事件处理器(或回调函数);事件分离器负责将请求事件传递给事件处理器。两个与事件分离器有关的模式是Reactor和Proactor。Reactor模式采用同步IO,而Proactor采用异步IO。

在Reactor中,事件分离器负责等待文件描述符或socket为读写操作准备就绪,然后将就绪事件传递给对应的处理器,最后由处理器负责完成实际的读写工作。


而在Proactor模式中,处理器--或者兼任处理器的事件分离器,只负责发起异步读写操作。IO操作本身由操作系统来完成。传递给操作系统的参数需要包括用户定义的数据缓冲区地址和数据大小,操作系统才能从中得到写出操作所需数据,或写入从socket读到的数据。事件分离器捕获IO操作完成事件,然后将事件传递给对应处理器。比如,在windows上,处理器发起一个异步IO操作,再由事件分离器等待IOCompletion事件。典型的异步模式实现,都建立在操作系统支持异步API的基础之上,我们将这种实现称为“系统级”异步或“真”异步,因为应用程序完全依赖操作系统执行真正的IO工作。


举个例子,将有助于理解Reactor与Proactor二者的差异,以读操作为例(类操作类似)。
在Reactor中实现读:

- 注册读就绪事件和相应的事件处理器
- 事件分离器等待事件
- 事件到来,激活分离器,分离器调用事件对应的处理器。
- 事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。
在Proactor中实现读:

- 处理器发起异步读操作(注意:操作系统必须支持异步IO)。在这种情况下,处理器无视IO就绪事件,它关注的是完成事件。
- 事件分离器等待操作完成事件
- 在分离器等待过程中,操作系统利用并行的内核线程执行实际的读操作,并将结果数据存入用户自定义缓冲区,最后通知事件分离器读操作完成。
- 事件分离器呼唤处理器。
- 事件处理器处理用户自定义缓冲区中的数据,然后启动一个新的异步操作,并将控制权返回事件分离器。

可以看出,两个模式的相同点,都是对某个IO事件的事件通知(即告诉某个模块,这个IO操作可以进行或已经完成)。在结构上,两者也有相同点:demultiplexor负责提交IO操作(异步)、查询设备是否可操作(同步),然后当条件满足时,就回调handler;不同点在于,异步情况下(Proactor),当回调handler时,表示IO操作已经完成;同步情况下(Reactor),回调handler时,表示IO设备可以进行某个操作(can read or can write)。

2、通俗理解

使用Proactor框架和Reactor框架都可以极大的简化网络应用的开发,但它们的重点却不同。

Reactor框架中用户定义的操作是在实际操作之前调用的。比如你定义了操作是要向一个SOCKET写数据,那么当该SOCKET可以接收数据的时候,你的操作就会被调用;而Proactor框架中用户定义的操作是在实际操作之后调用的。比如你定义了一个操作要显示从SOCKET中读入的数据,那么当读操作完成以后,你的操作才会被调用。

Proactor和Reactor都是并发编程中的设计模式。在我看来,他们都是用于派发/分离IO操作事件的。这里所谓的IO事件也就是诸如read/write的IO操作。"派发/分离"就是将单独的IO事件通知到上层模块。两个模式不同的地方在于,Proactor用于异步IO,而Reactor用于同步IO。

3、备注

其实这两种模式在ACE(网络库)中都有体现;如果要了解这两种模式,可以参考ACE的源码,ACE是开源的网络框架,非常值得一学。。

 

 

在高性能的I/O设计中,有两个比较著名的模式ReactorProactor模式,其中Reactor模式用于同步I/O,而Proactor运用于异步I/O操作。

 

       在比较这两个模式之前,我们首先的搞明白几个概念,什么是阻塞和非阻塞,什么是同步和异步,同步和异步是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。而阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作函数的实现方式,阻塞方式下读取或者写入函数将一直等待,而非阻塞方式下,读取或者写入函数会立即返回一个状态值。

  一般来说I/O模型可以分为:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞IO

 

   同步阻塞IO

   在此种方式下,用户进程在发起一个IO操作以后,必须等待IO操作的完成,只有当真正完成了IO操作以后,用户进程才能运行。JAVA传统的IO模型属于此种方式!

 

   同步非阻塞IO:

在此种方式下,用户进程发起一个IO操作以后边可返回做其它事情,但是用户进程需要时不时的询问IO操作是否就绪,这就要求用户进程不停的去询问,从而引入不必要的CPU资源浪费。其中目前JAVANIO就属于同步非阻塞IO

 

 

   异步阻塞IO

   此种方式下是指应用发起一个IO操作以后,不等待内核IO操作的完成,等内核完成IO操作以后会通知应用程序,这其实就是同步和异步最关键的区别,同步必须等待或者主动的去询问IO是否完成,那么为什么说是阻塞的呢?因为此时是通过select系统调用来完成的,而select函数本身的实现方式是阻塞的,而采用select函数有个好处就是它可以同时监听多个文件句柄,从而提高系统的并发性!

 

 

   异步非阻塞IO:

   在此种模式下,用户进程只需要发起一个IO操作然后立即返回,等IO操作真正的完成以后,应用程序会得到IO操作完成的通知,此时用户进程只需要对数据进行处理就好了,不需要进行实际的IO读写操作,因为真正的IO读取或者写入操作已经由内核完成了。目前Java中还没有支持此种IO模型。   

         搞清楚了以上概念以后,我们再回过头来看看,Reactor模式和Proactor模式。

首先来看看Reactor模式,Reactor模式应用于同步I/O的场景。我们分别以读操作和写操作为例来看看Reactor中的具体步骤:

读取操作

1. 应用程序注册读就需事件和相关联的事件处理器

2. 事件分离器等待事件的发生

3. 当发生读就需事件的时候,事件分离器调用第一步注册的事件处理器

4. 事件处理器首先执行实际的读取操作,然后根据读取到的内容进行进一步的处理

写入操作类似于读取操作,只不过第一步注册的是写就绪事件。

下面我们来看看Proactor模式中读取操作和写入操作的过程:

读取操作:

1. 应用程序初始化一个异步读取操作,然后注册相应的事件处理器,此时事件处理器不关注读取就绪事件,而是关注读取完成事件,这是区别于Reactor的关键。

2. 事件分离器等待读取操作完成事件

3. 在事件分离器等待读取操作完成的时候,操作系统调用内核线程完成读取操作,并将读取的内容放入用户传递过来的缓存区中。这也是区别于Reactor的一点,Proactor中,应用程序需要传递缓存区。

4. 事件分离器捕获到读取完成事件后,激活应用程序注册的事件处理器,事件处理器直接从缓存区读取数据,而不需要进行实际的读取操作。

Proactor中写入操作和读取操作,只不过感兴趣的事件是写入完成事件。

从上面可以看出,ReactorProactor模式的主要区别就是真正的读取和写入操作是有谁来完成的,Reactor中需要应用程序自己读取或者写入数据,而Proactor模式中,应用程序不需要进行实际的读写过程,它只需要从缓存区读取或者写入即可,操作系统会读取缓存区或者写入缓存区到真正的IO设备.

 

          综上所述,同步和异步是相对于应用和内核的交互方式而言的,同步 需要主动去询问,而异步的时候内核在IO事件发生的时候通知应用程序,而阻塞和非阻塞仅仅是系统在调用系统调用的时候函数的实现方式而已。

分享到:
评论

相关推荐

    vc网络高级编程

    - **开源框架介绍**:介绍一些流行的C++网络编程框架,如Boost.Asio、Muduo等,并分析它们的优点和应用场景。 - **社区与论坛**:推荐一些活跃度高、资源丰富的C++/VC++社区和论坛,方便学习者交流经验和解决问题。 ...

    boost asio 网络编程

    ### Boost Asio 网络编程 #### 一、Boost Asio 概述及网络编程基础...理解其核心概念和编程模型是构建高性能网络应用的基础。无论是进行简单的网络通信还是开发复杂的服务端系统,Boost Asio 都是一个值得信赖的选择。

    C++网络编程案例

    8. **高性能服务器设计**:高性能服务器通常采用事件驱动模型,如Reactor模式或Proactor模式,通过事件回调处理网络事件,以达到单线程处理大量连接的目的。C++的Epoll库在Linux系统中提供了高效事件通知机制。 9. ...

    Linux高性能服务器编程

    11.4 高性能定时器 11.4.1 时间轮 11.4.2 时间堆 第12章 高性能IO框架库Libevent 12.1 IO框架库概述 12.2 Libevent源码分析 12.2.1 一个实例 12.2.2 源代码组织结构 12.2.3 event结构体 12.2.4 往注册事件...

    网络编程第二卷(一本好书)

    通过ACEStreams框架,可以构建高性能的数据流处理管道。 ### 结论 《网络编程第二卷》不仅是一本技术手册,更是一部深度探索网络编程艺术的指南。通过细致入微地讲解ACE框架及其应用,本书为读者提供了在网络编程...

    socket高性能

    在IT行业中,Socket编程是网络通信的核心技术之一,特别是在高性能网络应用开发中,理解并掌握Socket的使用至关重要。"socket高性能"这个主题涉及到如何优化Socket通信,提高数据传输的效率和稳定性,确保在网络环境...

    scalable-io-in-java-中文.pdf

    在深入探讨《Scalable IO in Java》的中文版内容之前,首先需要了解Java中的I/O模型发展历程及其在服务器编程中的重要性。...通过学习本书,开发者能够掌握如何在Java中实现高性能的服务器端程序,并理解其背后的原理。

    netty+thrift高并发高性能

    常见的线程模型包括Reactor模式和Proactor模式,这些模式能够有效提高IO操作的效率,减少线程间的竞争。 4. **优化的数据结构**:Netty内部使用了高效的数据结构,如ByteBuf来管理内存,避免了频繁的内存复制操作,...

    高并发高性能服务器

    在服务器端,这可能涉及到多线程、多进程、异步IO、事件驱动(如Reactor模式或Proactor模式)等技术。 在高性能服务器的设计中,以下几个关键知识点尤为重要: 1. **负载均衡**:通过负载均衡技术,可以将来自不同...

    C#Socket高并发,socket高并发解决方案,CC++源码.zip.zip

    本资源"**C#Socket高并发,socket高并发解决方案,CC++源码.zip.zip**"提供了解决Socket高并发问题的代码示例,旨在帮助开发者理解和实现高性能的网络服务。 **C# Socket高并发** C#中的Socket编程主要基于System.Net...

    网络游戏-游戏服务器远程共享系统及方法.zip

    多线程、多进程技术可以并行处理多个玩家请求,异步IO模型如Reactor和Proactor模式则能提高服务器的响应速度。 4. **数据存储**:游戏数据的持久化存储通常使用关系型数据库(如MySQL)或非关系型数据库(如MongoDB...

    Java NIO:浅析I/O模型

    说起,然后接着阐述了阻塞和非阻塞的区别,接着介绍了阻塞IO和非阻塞IO的区别,然后介绍了同步IO和异步IO的区别,接下来介绍了5种IO模型,后介绍了两种和高性能IO设计相关的设计模式(Reactor和Proactor)。...

    Java工程师技能图谱.pdf

    3. IO模型和网络编程:IO模型包括BIO、NIO、AIO,以及Reactor/Proactor模式。网络编程方面需要理解NioEventLoopGroup/EventLoop、bossGroup/workerGroup、ByteBuff/Acceptor/Channel/Handler等核心基础类。 4. 网络...

    C++网游服务器端编程

    3. **高性能服务器架构**:常见的服务器架构有主从架构、无状态服务器、事件驱动架构(如Reactor模式和Proactor模式)。对于网络游戏,通常采用事件驱动模型,利用异步非阻塞I/O提高性能。 4. **数据库交互**:游戏...

    C++多线程聊天程序代码

    在IT领域,多线程编程是提升程序性能和并发处理能力的重要技术,特别是在开发聊天程序这类实时性要求较高的应用时。本篇文章将深入探讨标题所提及的"C++多线程聊天程序代码",以及如何利用多线程技术来构建一个聊天...

    ACE-5.4.1.zip

    通过深入研究ACE 5.4.1中的源代码,开发者可以学习到如何构建健壮、高性能的网络应用,同时也可以了解如何利用ACE提供的高级特性来简化网络编程的复杂性。这个库特别适用于需要高可靠性和低延迟的分布式系统,如实时...

    Asynchronous IO with Boost.Asio - Michael Caisse - CppCon 2016.pdf

    这个文档和其中的知识点对熟悉C++编程以及希望利用Boost库进行网络编程的开发者具有参考价值。以下是文档中所涉及的知识点详解: 1. 异步I/O概念 文档以一个生活场景为引,描述了异步I/O的直观概念。通过“请帮我做...

    netty原理的讲解

    总而言之,Netty通过优化的NIO模型、Reactor模式和高度可定制的处理流程,为Java开发者提供了构建高性能网络应用的强大工具。学习Netty不仅需要理解IO流的演变,还需要掌握其独特的设计理念和实现机制。通过深入学习...

Global site tag (gtag.js) - Google Analytics