事件处理模式

使用反应器(Reactor)结构化模式,事件驱动的应用可以多路分解并分配从一个或者多个客户机发送给应用的服务请求。反应器模式引入的结构“逆转”了应用中的控制流,这就是所说的好莱坞原则(“不要打电话给我们,我们会打电话给你的”)。然而它的事件分解是串行的。

主动器(Proactor)结构模式使事件驱动应用能有效地多路分解和分配由完成的异步操作所触发的服务请求。能获得并发的性能优势。

异步完成标记(Asynchronous Completion Token)设计模式使应用程序能对它在服务中调用异步操作而引起的响应进行有效地多路分解和处理。

一旦完成了连接和初始化,接受器-连接器(Acceptor-Connector)设计模式将网络化系统中同级服务的连接和协作初始化与随后进行的处理分开。接受器-连接器允许应用程序配置它们的连接拔掉结构,进行这种配置不依赖于应用程序所提供的服务。该模式可以置于反应器或者主动器之上,处理那些和建立服务间连接关系有关的事件。

3.1反应器

1.问题

在分布式系统,特别是服务器中的事件驱动应用,必须随时准备同时处理多个服务请求,即使这些请求在应用程序中最终还是被串行处理的。因此,在顺序执行特殊的服务之前,一个事件驱动应用程序必须先将并发到达的指示事件多路分解和分配给相应的服务实现。要有效地解决这些问题,需要考虑以下四个强制条件:

1)为了提高可扩展性和响应性能,应用程序不应该被单个指示事件源所阻塞,而排斥其他的事件源,否则来降低服务器对客户机的响应能力。

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

3)新的或改进的服务应该很容易地集成已有的指示事件多路分解和分配机制。

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

2.解决方案

同步等待多个事件源(如连接的Socket句柄)的指示事件到达。将对事件多路分解以及分配处理事件的服务的机制进行集成;将事件多路分解和分配机制从服务中对指示事件的与应用有关的处理分离出去。

细节:对于应用程序提供的每个服务,引入一个单独的事件处理程序处理某一个事件源的某一类型的事件。在反应器中注册所有的事件处理程序,反应器使用一个同步事件多路分解器等待一个或多个事件源的指示事件。发生指示事件后,同步事件多路分解器通知反应器,后者同步地分配与事件相关的事件处理程序,以便这些事件处理程序可以执行请求的服务。

3.结构

操作系统提供句柄(handle)来识别像网络连接或打开文件这样的事件源,事件源产生指示事件并对它的进行排队。指示事件可以来自于外部,也可以来源于内部。一旦一个事件源产生了一个指示事件,该提示事件就被送入相关句柄的队列中,句柄被标记为“就绪”。这样不会阻塞调用线程。

同步事件多路分解器(synchronous event demultiplexer)是一个函数。调用该函数,可以等待发生在一组句柄(句柄集)上的一个或多个指示事件。该函数在开始一直阻塞着,直到句柄集上的指示事件通知同步事件多路分解器“该句柄集上的一个或多个句柄变为‘就绪’”,这就意味着在没有阻塞的情况下可以启动一个对句柄的操作。

事件处理程序定义一个由一个或多个钩子方法组成的接口。钩子方法代表操作,这些操作可用于处理与应用有关的发生在与某事件处理程序相关联的句柄上的指示事件。

具体事件处理程序(concrete event handle)是实现应用程序所提供的特定服务的事件处理程序。每个具体事件处理程序都和一个句柄相关,句柄决定应用程序中的服务。特别是具体事件处理程序实现了钩子方法,这些钩子方法负责处理通过对应的句柄接收来的指示事件。将服务结果写到句柄上,并返回给调用者。

反应器(reactor)定义了一个接口,允许应用程序注册或删除事件处理程序及其相应的句柄,并运行应用程序的事件循环。反应器使用同步事件多路分解器等待在句柄集上发生指示事件。当有指示事件时,反应器首先从发生指示事件的句柄上将每个指示事件多路分解给相应的事件处理程序,然后在句柄上分配合适的钩子方法以处理这些事件。

4.实现

反应器模式的各个部分分成两层:

·多路分解/分配基础设施层的组件。本层执行一个通用的,与应用无关的策略,用于将指示事件多路分解到事件处理程序,然后分配相应的事件处理程序钩子的方法。

·应用层组件。本层定义具体事件处理程序,在具体事件处理程序的钩子方法中进行与应用有关的处理。

1)定义事件处理程序接口。事件处理程序具体指定了由一个或几个钩子方法组成的接口。这些钩子方法代表了处理由反应器接收并分配的指示事件件可用的服务集。

1.1)确定分配目标的类型。为实现反应器的分配策略,一个句柄可以有两类事件处理程序。

·事件处理程序对象(event handler object)。在面向对象的应用中,将事件处理程序与句柄结合起来的一个常用的方法是建立一个事件处理程序对象。

·事件处理程序函数(event handler function)。将事件处理程序与句柄结合起来的另一个策略是向反应器注册一个指向函数的指针。使用函数指针作为分配目标,不用定义继承事件处理程序基类的新的子类,就可以很方便地注册回调函数。

1.2)确定事件处理程序分配接口策略。下一步必须定义事件处理程序时支持的接口类型。假设使用事件处理程序对象而不用函数指针,这里有两种大致的策略:

·单方法分配接口策略(single-method dispatch interface strategy)。该接口只包括一个事件处理方法。使用单方法分配接口策略,就可以在不改变类接口的情况下,支持新的指示事件类型。但是该策略要求在具体事件处理程序的方法中大量使用switch和if语句来处理特定事件,从而降低了可扩展性。

·多方法分配接口策略。该策略是为处理每一类事件创建一个单独的钩子方法。这比单方法分配接口策略更具有扩展性,因为是由反应器实现而不是由具体事件处理程序的方法来进行多路分解的。

2)定义反应器接口。应用程序使用反应器接口注册或删除事件处理程序及相应的句柄,并调用应用程序的事件循环。

3)实现反应器接口。

3.1)开发反应器的实现层次。

3.2)选择一种同步事件多路分解器机制。

3.3)实现一个多路分解表。除了调用同步事件多路分解器等待句柄集发生指示事件之外,反应器实现还要维护一个多路分解表。该表是一个管理者,包含一个格式为<句柄, 事件处理程序, 指示事件类型>的三元组表。反应器实现使用句柄作为关键字和多路分解表中的事件处理程序建立关联。该表也存储了事件处理程序注册到句柄上的指示事件的类型。

3.4)定义反应器的具体实现。

4)确定应用程序所需要的反应器数量。对于某些实时应用程序,通过将不同的反应器与具有不同优先级的线程相关联,可以为不同类型的同步操作处理指示事件提供了不同等级的服务质量。

5)实现具体事件处理程序。

5.1)确定维护具体事件处理程序状态的策略。一个事件处理程序需要维护与特定请求有关的状态信息。

5.2)实现用一个句柄配置各具体事件处理程序的策略。

·硬编码。该策略将句柄或者句柄的包装器外观硬编码到具体事件处理程序中。这种方法很容易实现,但是如果对于不同的用况必须将不同类型的句柄或IPC机制配置到事件处理程序中时,重用性不好。

·类属(generic)方法。一个更通用的策略是在模板化事件处理程序类中以类型为参数来实例化包装器外观。这种方法能产生更灵活和可重用的事件处理程序,虽然在总使用一种句柄类型或者IPC机制的情况下,这种通用性是不必要的。

5.3)实现具体事件处理程序的功能。

5.结论

优点:

1)事务分离。反应器模式将与应用程序无关的多路分解和分配机制和与应用有关的钩子方法功能分开。与应用无关的机制被设计成可重用的组件。该组件知道如何多路分解指示事件并分配由事件处理程序定义的适当的钩子方法。相反,钩子方法中与应用有关的功能知道如何完成特定类型的服务。

2)模块化,可重用性与可配置性。该模式将事件驱动的应用功能分解成几个组件。它们被松散地集成在反应器中,这种模块化有助于更高级的软件组件重用。

3)可移植性。只要把反应器接口从实现中使用的低层操作系统的同步事件多路分解器函数中分离出来,就可以很容易地跨平台移植使用反应器模式的应用程序。

不足:

1)应用范围受到限制。如果操作系统支持对句柄集的同步事件多路分解,使用反应器模式会很高效。然而,如果操作系统并不提供这类支持,可以在反应器实现中使用多线程模拟反应器模式的语义。

2)非抢先的方式(Non-pre-emptive)。事件处理程序不应该执行耗时长的操作,因为这样会阻塞整个进程,并妨碍反应器对连接到其他句柄上的客户机的响应。

3)调试和测试的复杂性。

转载于:https://www.cnblogs.com/pennant/archive/2012/09/13/2682765.html

《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(7)--- 事件处理模式与反应器...相关推荐

  1. 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(3)--- 服务访问和配置模式...

    服务访问和配置模式 包装器外观(Wrapper Facade)设计模式把现有的非面向对象的API所提供的函数和数据,封装在更加简洁的.健壮的.可移植的.可维护的和内聚的面向对象的类接口里面.常常应用包 ...

  2. 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(12)--- 策略化加锁...

    4.2策略化加锁(Strategized Locking) 1.问题 运行在多线程环境中的组件必须保护其临界区不被客户机并发访问.同步机制与组件功能的集成需要解决以下两个强制条件: 1)不同的应用程序 ...

  3. 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(17)--- 领导者/追随者...

    5.4领导者/追随者(Leader/Follower) 1.问题 多线程是实现并发处理多事件的应用程序的一种常用技术.然而,很难实现高性能的多线程服务器应用程序.这些应用程序通常处理大量同时到达的多类 ...

  4. 《面向模式的软件体系结构2-用于并发和网络化对象模式》读书笔记(13)--- 线程安全接口和双检查加锁优化...

    4.3线程安全接口(Thread-Safe Interface) 1.问题 多线程组件通常包括多个可被公共访问的接口方法以及可以改变组件状态的私有方法.为了避免出现竞争条件,可以使用一个组件内部的锁对 ...

  5. 面向模式的软件体系结构(卷1-5

    面向模式的软件体系结构(卷1-5 [一日养生24法].宋爱莉.插图版.pdf: http://www.t00y.com/file/60331740 [一桶金]--颠覆传统赚钱方式的系统创富法则.艾莫. ...

  6. 面向模式的软件体系结构

    面向模式的软件体系结构,卷2,详细介绍并发网络服务器 C 语言常见问题集 转载于:https://www.cnblogs.com/unixshell/p/3825490.html

  7. 《软件建模与设计: UML、用例、模式和软件体系结构》一一2.10 UML扩展机制

    本节书摘来自华章计算机<软件建模与设计: UML.用例.模式和软件体系结构>一书中的第2章,第2.10节,作者:(美)Hassan Gomaa,更多章节内容可以访问云栖社区"华章 ...

  8. 《软件建模与设计: UML、用例、模式和软件体系结构》一一3.1 软件生存周期模型...

    本节书摘来自华章计算机<软件建模与设计: UML.用例.模式和软件体系结构>一书中的第3章,第3.1节,作者:(美)Hassan Gomaa,更多章节内容可以访问云栖社区"华章计 ...

  9. 《软件建模与设计: UML、用例、模式和软件体系结构》一一3.2 设计验证和确认...

    本节书摘来自华章计算机<软件建模与设计: UML.用例.模式和软件体系结构>一书中的第3章,第3.2节,作者:(美)Hassan Gomaa,更多章节内容可以访问云栖社区"华章计 ...

最新文章

  1. jQuery循环使用相同类的元素
  2. Spring的事务控制-基于注解的方式
  3. 【转载】一文彻底拿下Java异常
  4. linux查看vxlan命令,[svc]linux上vxlan实战
  5. 【Python】第一个程序---Helloworld!
  6. IOS之NSValue整理
  7. React 第六章 事件的绑定
  8. 为什么要使用MQ消息中间件?
  9. java9 javascript_JS(JavaScript)的j进一步了解9(更新中···)
  10. 2020 OPPO开发者大会:融合共创,打造多终端、跨场景的智能化生活
  11. 查看mysql某人执行了什么语句_一条 SQL 语句是如何在 MySQL 中执行的
  12. 字节跳动单点恢复功能及 Regional CheckPoint 优化实践
  13. eslint 换行_给 eslint 写一个插件
  14. win10下安装deepin双系统的坑:安装完成一直黑屏进不去系统
  15. TP6基础知识【新框架】
  16. pytorch中num_workers详解
  17. skywalking源码分析第十八篇一agent端Trace三部曲一Span栈桢机制
  18. GEE--LandTrendr
  19. 洪特规则计算孤立原子/离子磁矩
  20. Q2营收净利润双降 后疫情时代百事可乐的“快乐水”生意有多难?

热门文章

  1. gitlab8.2-8.16-8.17-9.0升级
  2. MySQL学习之二进制日志
  3. 原型模式Prototype,constructor,__proto__详解
  4. locate,find
  5. apache2.4中layout模块和ssi模块的冲突
  6. Android绘制流程
  7. 详解 CSS 属性 - 伪类和伪元素的区别
  8. knowledgetree汉化出现错误
  9. 吐血总结|史上最全的MySQL学习资料!!
  10. 牛客练习赛3 E - 绝对半径2051