zoukankan      html  css  js  c++  java
  • 并发网络模块化 读书笔记转

      目前有很多网络库,其中libevent是基于Reactor实现的,而boost.asio是基于Proactor实现的。Reactor和Proactor模式的主要区别就是真正的操作(如读/写)是由谁来完成的,Reactor中需要应用程序自己读取或者写入数据,而在Proactor模式中,应用程序不需要进行实际的读/写过程,操作系统会读取缓冲区或者写入缓冲区到真正的IO设备,应用程序只需要从缓冲区读取(操作系统已经帮我们读好了)或者写入缓冲区(操作系统会帮我们写入)即可。在Proactor模式中,用户发起异步操作之后就返回了,让操作系统去处理请求,然后等着回调到完成事件函数中处理异步操作的结果。

    2.3主动器(Proactor)

    1.问题

          异步处理多个服务请求通常可以改善分布式系统中的事件驱动应用程序的性能。完成异步服务处理后,应该程序必须处理由操作系统发出的表示异步计算结束的相应的完成事件。要有效地支持这种异步计算模型,需解决以下四个强制条件:

          1)为了改进可扩展性和延迟性能,一个应用程序必须在禁止耗时长的操作过分地延迟其他操作处理的情况下同时处理多个完成事件。

          2)为了使吞吐率最大,应避免CPU之间的任何不必要的语境切换,同步和数据移动。

          3)将新的或改进的服务与已有的完成事件多路分解与分配机制集成所花的代价要最少。

          4)应用程序代码应尽量不受多线程和同步机制复杂性的影响。

    2.解决方案

          将应用服务分成两部分:异步执行的耗时长的操作和在这些操作完成后处理其结果的完成处理程序。将异步操作完成时对完成事件的多路分解和将它们分配到相应的处理它们的完成处理程序这两部分集成起来。将完成事件多路分解与分配机制与完成处理程序中与应用有关的对完成事件的处理分开。

          具体地说就是:为应用程序所提供的每个服务引入一个异步操作。由这些异步操作通过一个句柄和完成处理程序来主动地初始化对服务请求的处理,完成处理程序处理包含这些异步操作结果的完成事件。例如,可以在应用程序中由启动程序调用异步操作来接受从远程应用程序发来的连接请求。异步操作由异步操作处理器执行。操作执行完毕后,异步操作处理器在完成事件队列中插入一个包含该操作结果的完成事件。

          称为主动器的异步事件多路分解器等待该队列。异步事件多路分解器从队列中删除一个完成事件后,主动器向该异步操作相应的与应用有关的完成处理程序多路分解和分配该事件,然后该完成处理程序处理异步操作的结果,可能要调用其他的异步操作,这些异步操作遵循上述活动链。

    3.结构

          操作系统提供句柄(handle)以标识实体(如网络连接)或打开文件(能产生完成事件),可以响应外部服务请求(如远程应用程序发来的连接或数据请求)而产生完成事件,也可以响应应用程序内部产生的操作(如超时或异步I/O系统调用)而产生完成事件。

          异步操作(asynchronou operation)表示在实现如通过socket句柄异步读写数据这样的服务时要使用的耗时长的操作。调用一个异步操作后,执行该异步操作而不阻塞调用者的控制线程。这样调用者可以执行其他操作。如果一个操作必须等待另一个事件的发生,如远程应用程序产生的一个连接请求,则它要被延迟到事件到达后才开始执行。

          完成处理操作(Completion handler)定义了一个由一个或多个钩子方法组成的接口,可以使用这些方法处理与应用有关的完成事件中返回的信息。完成事件是在异步操作执行完后产生的。

          

          实现继承的钩子方法后,具体完成处理程序(concrete completion handler)特化了一个完成处理程序以定义一个特定的应用服务。当与完成处理程序相关的异步操作执行完后,钩子方法接收并处理包含在完成事件中的结果信息。一个具体完成处理程序对应于一个可以用于调用异步操作的句柄。

          

          异步操作处理器(asychronous operation processor)调用某一个句柄的异步操作并运行到结束,通常由操作系统内核实现异步操作处理器。异步操作执行完后,异步操作处理器产生相应的完成事件。根据操作所针对的句柄,异步操作处理器将该完成事件插入到与句柄相对应的完成事件队列(completion event queue)中,队列中保存有要被多路分解到相应的完成处理程序上的完成事件。

          

          异步事件多路分解器(asynchronous event demultiplexer)是一个函数,它等待在异步操作执行完后将被插入到完成事件队列中的完成事件。然后异步事件多路分解器函数将一个或多个完成事件从队列中删除,并返回给调用者。

          主动器(proactor)为应用程序进程或线程提供事件循环。在该事件循环中,主动器调用一个异步事件多路分解器,等待完成事件的发生。当事件到达时,异步事件多路分解器返回。然后主动器将该事件多路分解给相应的完成程序,并为该处理程序分配合适的钩子方法,以处理完成事件的结果。

          

          启动程序(initiator)是应用程序内部的一个实体,它调用异步操作处理器的异步操作。通常启动程序处理所调用异步操作的结果,在这种情况下,它就担当了具体完成处理程序的角色。

          

    4.实现

          主动器模式中的参与者可以划分为两层:

          ·多路分解/分配基础设施层组件。该层按照通用的,与应用无关的策略执行异步操作。它也将异步操作的完成事件多路分解和分配给相应的完成处理程序。

          ·应用程序层的组件。本层定义了执行与应用有关的服务处理的异步操作和具体完成处理程序。

    1)将应用程序服务分成异步操作和完成处理程序。为了实现主动器模式,必须将应用服务中通过句柄对异步操作的激活与对这些操作结果的处理已分开。该活动的结果是一组异步操作,一组完成处理程序,以及一组异步操作与完成处理程序之间的关联关系。

    2)定义完成处理程序接口。完成处理程序中的接口由一个或多个钩子方法组成。这些钩子方法表示对与应用有关的完成事件的完成处理,这些完成事件是在异步操作执行完毕后产生的。

      2.1)定义一种传递异步操作结果的类型。当异步操作完成或者被取消后,必须将完成事件结果传递给完成处理程序。这些结果表示异步操作是成功还是失败,以及成功传送的字节数。

      2.2)确定分配目标的类型。有两类完成处理程序可以与句柄关联,并作为主动器分配机制的目标:对象和函数指针。

      2.3)定义完成处理程序分配接口策略。单方法分配接口策略和多方法分配接口策略。

    3)实现异步操作处理器。

      3.1)定义异步操作接口。可以向异步操作传递不同的参数,如句柄、数据缓冲区、缓冲区长度以及操作完成后执行完成处理所需的信息。设计启动程序用以调用异步操作处理器的异步操作的程序接口时,要解决两个问题:

      ·尽量增加可移植性和灵活性。

      ·有效地,简洁地处理多个完成处理程序,主动器和完成事件队列。

      3.2)选择异步操作处理机制。当启动程序调用一个异步操作时,异步操作处理器在不阻塞启动程序的控制线程的情况下执行该操作。一个异步操作处理器提供管理异步完成标识和异步执行操作的机制。当操作结束后它也产生完成事件,并将该事件插入到适当的完成事件队列中。

             有些异步操作处理器允许启动程序取消异步操作,但完成事件还是要产生的。这样,完成处理程序就可以正确地重新利用异步完成标记和其他资源。

    4)定义主动器接口。应用程序使用主动器接口来调用一个事件循环,从完成事件队列中删除完成事件,将完成事件多路分解给相应的完成处理程序并分配相应的钩子方法。

    5)实现主动器接口。

      5.1)开发主动器实现层。

      5.2)选择完成事件队列和异步事件多路分解器机制。

      ·FIFO多路分解。这一类异步事件多路分解器函数等待与完成事件队列相关联的任何异步操作所对应的完成事件,按照这些完成事件的插入顺序删除这些事件。

      ·选择性的多路分解。这种类型的异步事件多路器函数有选择性地等待完成事件的特定子集,当函数被调用时必须显式地传递这些完成事件。

      5.3)确定如何向完成处理程序多路分解完成事件。向完成处理程序多路分解完成事件的一个有效的,简洁的策略是使用异步完成标记模式。使用这种策略的话,一旦启动程序调用异步操作,异步操作处理器就会收到用于指导后续完成处理的信息。

             异步操作完成时,异步操作处理器产生相应的完成事件,将完成事件和异步完成标记关联起来,并将修改后的完成事件插入到相应的完成事件队列中。异步事件多路分解器从它的完成事件队列中删除完成事件后,主动器实现可以作为完成事件的异步完成标记在常数时间O(1)内多路分解给指定的完成处理程序。

      5.4)确定如何为指定的完成处理程序分配钩子方法。

      5.5)定义具体的主动器实现。

    6)确定应用程序中主动器的数量。

    7)实现具体完成处理程序。

      7.1)确定维护具体完成处理程序的状态的策略。

      7.2)选择用句柄配置具体完成处理程序的机制。

      7.3)实现完成处理程序的功能。

    8)实现启动程序。

    5.结论

    优点:

          1)事务分离。

          2)可移植性。

          3)并发机制的封装。将主动器和异步操作处理器分开的一个好处是应用程序可以用不同的并发策略配置主动器,而不会影响其他应用程序组件和服务。

          4)将线程化与并发控制分开。

          5)性能。

          6)简化应用程序的同步。

    不足:

          1)应用范围受到限制。

          2)编程、调试和测试复杂性。

          3)异步地调度、控制和取消正在执行的操作

    接受器 - 连接器(Acceptor - Connector)

    1.问题

          在面向连接的网络化系统中,应用程序通常包含相当大量的用于建立连接和初始化服务的配置代理。这些配置代码大多独立于服务对在连接传输端点之间交换的数据所进行的处理。因此配置代码与服务处理代码之间紧密耦合是不理想的,因为这样不能解决以下四个强制条件:

          1)它应该很容易地改变连接角色,以支持不同的应用特征。

          2)应很容易地增加服务,服务实现和通信协议的种类,而不影响已有的连接建立和服务初始化配置代码。

          3)连接建立和服务初始化策略的改变要比应用程序实现的通信协议和服务的改变频率少。

          4)对大规模网络化系统,应能通过使用高级的操作系统特性,如异步连接机制来降低连接建立延迟。

    2.解决方案

          将网络化应用中对等体服务的连接和初始化工作,与连接和初始化后这些服务所执行的处理分开。

          具体地说:在对等体服务处理程序中封装应用服务。每个服务处理程序实现网络化应用中端到端的一半服务。使用两个工厂连接和初始化对等体服务:接受器和连接器。这两个工厂相互合作,创建在两个对等体服务处理程序与它们的两个连接的传输端点之间的全关联,每个传输端点封装在一个传输句柄中。

          接受器工厂代表相关的对等体服务处理程序,在由远程对等体服务处理程序发出的连接请求事件到达后被动地建立连接。反过来,连接器工厂代表对等体服务处理程序主动地与指定的远程对等体服务处理程序建立连接。

          连接建立后,接受器和连接器工厂初始化相应的对等体服务处理程序,向它们传送各自的传输句柄。然后对等体服务处理程序使用传输句柄通过连接的传输端点交换数据,进行与应用有关的处理。一般来说,在连接和初始化后,服务处理程序并不与接受器和发送器交互。

    3.结构

          被动模式的传输端点是一个工厂,它侦听连接请求,接受连接请求和建立传输句柄,传输句柄中封装了新连接的传输端点。可以通过连接的传输端点读写相应的传输句柄来交换数据。

           

          服务处理程序定义了网络系统中端到端的一半服务。在这个端到端的服务中一个具体的服务处理程序通常既具有客户机角色又具有服务器角色。在对等使用的情况下,它可以同时扮演这两个角色。一个服务处理程序提供了一个激活钩子方法,用于在连接到其对等体的服务处理程序后进行初始化。另外,服务处理程序还包括一个封闭传输端点的传输句柄,如数据模式套接字句柄。一旦连接上,服务处理程序就使用传输句柄与对等体服务处理程序通过它们的连接传输端点交换数据。

           

          接受器是一个工厂,它实现的功能包括被动地建立被连接的传输端点,创建和初始化相关的传输句柄和服务处理程序。一个接受器提供两个方法:连接初始化和连接完成,这两个方法在被动模式传输端点的帮助下实现上述功能。

          调用初始化方法时,接受器将被动模式传输端点绑定到一个传输地址上,如一个TCP端口号和IP主机地址,它被动地侦听连接请求。

          当连接请求到达时,接受器的连接完成方法执行下面3个步骤:

          ·首先,它用被动模式传输端点创建一个连接的传输端点,并在传输句柄中封装该端点。

          ·第二,它创建一个服务处理程序,用于处理对等体服务处理程序通过连接的传输端点发出的数据请求。

          ·第三,它将传输句柄存储在相应的服务处理程序中,然后调用服务处理程序的激活钩子方法,该方法让服务处理程序自己完成初始化。

          连接器也是一个工厂,它实现的功能包括主动地建立连接的传输端点,初始化其相应的传输句柄和服务处理程序。它提供2个方法:连接启动和连接完成方法。

          向连接启动方法传给一个已有的服务处理程序,该方法为它和接受器建立一个连接的传输端点。正如前面介绍的,该接受器一定正在侦听在某一传输地址上的连接请求。

          将连接器的连接启动方法和完成方法分开,这样可以使连接器支持透明的同步和异步的连接建立。

          ·对于同步的情况,激活连接请求的连接器阻塞其调用者,直到传输端点被连接上。以后,连接器直接调用服务处理程序的激活钩子方法。

          ·对于异步的情况,异步运行连接请求,连接器的激活方法立即返回。只有在连接器得到传输端点已异步地完成了连接的通知后,连接完成方法才激活服务处理程序。

           

          无论是同步还是异步地连接传输端点的,在连接上传输端点事,接受器和连接器都通过调用其激活钩子方法来初始化一个服务处理程序。以后,服务处理程序一般不需要与连接器和接受器工厂交互。

          分配器负责多路分解表示不同类型服务请求(如连接请求和数据请求)的指示事件。

          

          ·对于接受器,分配器多路分解从封装传输端点的一个或多个传输句柄中接收来的连接指示事件。多个接受器可以注册同一个分配器,分配器替它们侦听来自于对等体连接器的连接请求。

          ·对于连接器,分配器多路分解因响应异步激活的连接而到达的完成事件。为了处理这种情况,连接器向一个分配器注册它自己,以接收这些连接完成事件,然后分配器运行它的事件循环。当完成事件到达时,它通知相应的连接器。然后连接器调用指定的服务处理程序的激活钩子方法,让服务处理程序来初始化自己。因此,一个分配器和连接器可以代表多个服务处理程序异步地激活和完成连接。

                注意,异步连接建立不需要使用分配器,因为启动连接的线程会因等待连接完成事件而阻塞。因此,该线程可以直接激活服务处理程序。

          具体的服务处理程序定义与应用有关的部分端到端服务,由具体接受器或具体连接器激活这部分服务。具体接受器用具体服务处理程序。传输端点和这些服务处理程序使用的传输句柄来实例化通用接受器。类似地,具体连接器也实例化通用连接器。

    4.实现

          接受器 - 连接器模式中的各组成部分可以分解成以下三层:

          ·多路分解/分配基础设施层组件。该层执行通用的与应用无关的事件分配策略。

          ·连接管理层组件。该层执行通用的与应用无关的连接和初始化服务。

          ·应用层组件。该层对上两层的通用策略进行定制,它使用了子类派生,对象组合和/或参数化类型的实例化等方法,以创建具体组件这些具体组件用于建立连接,交换数据和执行与服务有关的处理。

    1)实现多路分解/分配基础设施组件层。

          1.1)选择传输机制,这些机制包括:

                ·被动模式传输端点组件。

                ·连接的传输端点组件。

                ·传输地址组件。

                ·传输句柄组件。

          1.2)实现分配机制。这些机制由分配器和事件处理程序组件组成。分配器负责将请求与对应的接受器,连接器和服务处理程序联系起来。事件处理程序定义了由事件驱动的应用程序中服务所提供的事件处理接口。

    2)实现连接管理组件层。本层负责创建服务处理程序,主动或被动地将服务处理程序连接到远程服务处理程序上,以及在连接后激活服务处理程序。这一层的所有组件都是通用的,并依赖于具体的IPC机制,具体的服务处理程序,具体的接受器和具体的连接器。在连接管理层中有三个主要的组件:服务处理程序,接受器和连接器。

          2.1)定义通用的服务处理程序接口。服务处理程序提供了一个通用的接口,它是由客户机,服务器或者在端到端的服务中两者(客户机和服务器)共同定义的服务。该接口包括初始化服务处理程序,执行它定义的服务以及维护用于通信的IPC机制等方法。

          2.2)定义一个通用的接受器接口。接受器组件中实现一个通用的策略,该策略用于被动地建立连接,建立的初始化具体的服务处理程序,这些具体的服务处理程序利用这些连接与对等体服务处理程序交换数据。接受器中也定义一个初始化方法,供应用程序调用这个方法,用于向网络中其他应用程序通告它的被动模式传输端点。

          2.3)实现通用的接受器方法。应用程序通过调用其初始化方法来初始化接受器。调用初始化方法时要有一个指明传输地址(如本地主机IP名和TCP端口号)的参数。接受器使用这个地址参数侦听对等体连接器启动的连接请求。它通过接受器的具体接受器子类或通过类型化参数将这个地址传递给配置到通用接受器中的具体IPC连接机制。然后IPC连接机制就初始化接受器的被动模式传输端点,将它的地址告知要与该接受器建立连接的远程应用程序。

          2.4)定义通用的连接器接口。连接器组件实现了用于主动建立连接和初始化服务处理程序的通用策略,这些服务处理程序负责处理连接上的请求和响应事件。

          2.5)实现通用连接器方法。应用程序用连接器的connect()方法来启动一个连接,具体连接器可以使用该模板方法,在不改变连接器接口和实现的情况下透明地修改主动连接策略。因此,connect()将其连接策略中的具体步骤交给钩子方法去完成,具体连接器可以重载这些钩子方法以进行个性化的操作。

    3)实现应用层的组件。本层实现具体服务处理程序,具体接受器和具体连接器。 

    5.结论

    优点:

          1)可重用性,可移植性和可扩展性。接受器 - 连接器模式将连接和初始化服务处理程序的机制与在此之后进行的服务处理分开。接受器和连接器中与应用无关的机制是可重用的组件。

          2)健壮性。接受器 - 连接器模式将服务处理程序与接受器分开。这种分离能确保被动模式传输端点不能用于读/写数据。这种增加了类型安全性,能消除使用弱类型的网络编程接口时经常会出现的一类错误。

          3)高效性。接受器 - 连接器模式可以在延迟很大的广域网中异步地和高效地与大量主机主动地建立连接。

    不足:

          1)增加了间接性。与直接使用底层的网络编程接口相比,接受器 - 连接器模式是不直接的。

          2)增加了复杂性。对于只连接到一个服务器,使用单一网络编程接口执行一个服务的简单客户机应用程序,接受器 - 连接器模式增加了不必要的复杂性。不过使用通用的接受器和连接器包装器外观可以使开发人员不用考虑令人厌烦的,易出错的和不可移植的低层网络编程机制,从而简化了应用程序的设计。 

    http代理服务器(3-4-7层代理)-网络事件库公共组件、内核kernel驱动 摄像头驱动 tcpip网络协议栈、netfilter、bridge 好像看过!!!! 但行好事 莫问前程 --身高体重180的胖子
  • 相关阅读:
    js格式化文件大小,单位:Bytes、KB、MB、GB
    Java如何大批量从json数据源中按指定符号隔字符串,并修改、删除数据
    ExtJs定时消息提示框,类似于QQ右下角提示,ExtJs如何定时向后台发出两个请求并刷新数据实例
    Java jxl导入excel文件,导入的数字、身份证号码、手机号变成了科学计数法,解决方案
    Java 防SQL注入过滤器(拦截器)代码
    mysql8源码安装和MGR
    linux基础
    ThreadLocal
    redis缓存雪崩、穿透、击穿概念及解决办法
    ThreadLocal可能引起的内存泄露
  • 原文地址:https://www.cnblogs.com/codestack/p/15173131.html
Copyright © 2011-2022 走看看