UML软件工程组织

面向对象的分布式开发系统-理论篇(2)
作者:陈立峰 本文选自:赛迪网 2003年04月14日

 

 3.布式系统的关键技术



  3.1面向对象技术Object-Oriented

  客户/ 服务器模式,是典型的分布式计算模型。在此模式下,客户端建立连接到服务器,通过相互约定的协议通讯,以达到交换信息的目的。SoftEngine 核心的通讯通道封装了这些复杂的底层细节。通过多层的封装技术,将底层对象与应用对象完全隔离。SoftEngine 只在组件区域为应用提供了一些抽象类作为"软总线"的接口。如下图所示:



  图表 2 Abstract class is the interface of Soft-Bus.

    Application Objects : 应用对象 System Objects: 系统对象

    Infrastructure Objects: 底层对象 Abstract Class: 抽象类

  设计一个可重用的面向对象软件不是简单的事,一个分布式的重用系统更是困难的事。在SoftEngine 的基础之上却很容做到。因为其本身的体系结构是对象化设计的,也是可重用的 。

  在组件区域内,开发人员只需关注应用的业务,继承接口抽象类,实现所定义的业务流程,通过发布实例化的应用对象,构造应用系统。这种面向对象的开发模式,对程序员来讲是非常简单,非常有效的,也可从繁重的体力劳动(编码)中解脱出来,更多的精力用于设计工作。

  组件区域中的应用对象,是可被重用。按照一定的发布方式,可以在不同的SoftEngine 系统中再次利用。可被重用性不再取决于编码的质量,而在于如何设计出好的应用业务逻辑流程。关于这一点,我们将在后续的流水线式设计模式中讨论。



  3.2任务驱动Task-Driven

  在SoftEngine 内部采用的是任务驱动。在这里所提到的任务驱动概念,不完全相同于一些专业任务驱动论文,更接近事件驱动(Event-Driven) 。也就是说,所有的对象在没有任务时,处于空闲状态;直到有任务(事件)到达,对象的运行模式才会转变为激活状态。

  在不同的对象间,传递任务是合作(collaborate) 的唯一方式。合作模式有两种:

  ·完全独立的模式(Individual)

  ·松散耦合模式(Loosely Coupled)

  下面图示了其中的不同:



  图表 3 Individual and loosely coupled collaboration

  ·对象A 和对象B 有次序地处理同一个任务,对象B 必须等待对象A 的处理结果。对象A 和对象B 的合作关系称为:松散藕合模式 。

  ·对象B 和对象C 分别处理不同的任务。这种关系称为:完全独立的模式。也就是说,对象C 需要的任务,不总是来自于对象B ,它们之间没有必要的关联。

  在完全独立模式,对象C 由于功能相对独立,无须等待想关数据,所以效率比较高,具有很高的实时性。但存在功能相对集中,适应性比较差,被可重用的可能性也相对减少的不足。松散耦合模式,为完成任务,将处理步骤/ 功能细分为不同的对象。使对象A 和B 的功能相对专一,适应性增强,可重用性也增加了。同时更据不同的功能效率可以方便的作负载均衡(Load balancing)调整。但是任务的多次投递,以及相对的耦合关系,也降低了局部的处理性能。就如下图所显示的两者的性能比较:



  图表 4 Performance of collaboration

  在实际应用开发中,如果选择完全独立的模式 或 松散耦合模式,取决于在设计阶段如何定义应用的业务流程。这将在后续章节: 流水线式设计模式中再次阐述 。

  每个被传送中的任务,都具有自己的生存周期(Live cycle),从产生到被丢弃。如下图生存周期图:



  图表 5 Live-cycle of task

    Created : 被产生 Forward: 正向传送

    Backward: 回送 Pending: 悬挂

    Timeout: 超时 Operating:处理

    Droped:被丢弃

  一个任务由某个功能对象产生,并传送(forward)到下一个目的对象,在那里将被处理之后,这个任务会被丢弃,或被返回(backward)到源对象。这是一个常规的任务生存周期,但如果在任务传递途中,发生如目标对象不可到达等阻碍,该任务将会被悬挂(pending) 。直到继续传送或超时(timeout)被丢弃。任务在传递中的安全问题,将会在后续的数据安全主题中讨论。



  3.3 分布式对象Distributed Object

  在上文提到,SoftEngine 由不同种类的对象构造,在发布实施角度上看,可分为三种: 本地(Local)

对象,远地(Remote) 对象,虚拟(Virtual) 对象 。



  图表 6 Local, Remote and Virtual Object

  在上图中:

  ·本地对象Local Object : 指分布在同一个SoftEngine 独体系统中的对象,互称为本地对象。如:在系统I 中的对象A 和B 互为本地对象 。

  ·远地对象Remote Object : 指分布在不同SoftEngine 系统中的对象(同一个群体系统)。 如: 对象A 和C ,以及B 和C 互为远地对象。对于系统II 中的C ,系统I 中的A 和B 属于远地对象的 。

  ·虚拟对象Virtual Object : 不同于本地和远地对象,虚拟对象不属于真实的对象,而是一个虚设的类型。真正的操作不在虚拟对象本身,只是远地对象在本地的映射。如:虚拟对象A,是A 在系统II 中的映射。对象C 向A发送的任务,会转送到远地对象A ,而C 不知道,也没有必要知道。同理,如果对象B 需要发送任务到C ,在系统I 中可定义C 的虚拟对象 。

  本地和远地对象是相互的关系。而虚拟对象只是一种映射,用于关联本地和远地对象,起到分布和

负载均衡的作用。三者之间的关系在开发中无须关心,只有在系统部署中,通过配置发布环境来确

定或改变。以下图为例,介绍负载均衡:



  图表 7 A load balance system

  在一个分布的系统中,有两个独立的运行系 统 I 和II 。其中有相同的对象A1, A2, A3, A4 被分别发布,他们所被加载的类是相同的,只是被定义的发布名称不同。如果再定义一个虚拟对象A 同时映射到A1 - A4 ,同时配置不同的策略,如负载均衡的循环法(Round-Robin) ,或冗余法(Hi-Available)。发送到A 的任务,会按照不同的策略分发到A1-A4 上。

  在应用对象开发测试完成后,部署的策略,包括:系统配置、对象配置、对象发布等信息,被定义在每个独体系统的配置文件中。通过这些配置文件,将会动态地构建出一个分布的网状系统,可以完成特定的应用功能。所以如此构成的分布式系统具备以下的体点:

  ·整个分布式系统由各种对象,以动态组件的方式构造。

  ·对象可以存在于任何网络(LAN/WAN) ,任何主机。

  ·通过配置,对象可以动态地加载/ 卸载。整个分布系统,始终处于动态调整状态。

  ·虚拟对象让本地对象忽视真实的远地对象的物理位置。

  ·开发与分布过程完全分离。在对象开发过程中,无需过多的考虑系统级的问题。



  图表 8 A distributed system



  3.4 数据安全Data-Safety

  应用系统所需的数据信息,在以任务的方式送入SoftEngine 系统内部后,任务将会被高效地传输

在每个独体系统内部,或群体系统的网络中。因此,如何保证任务的安全到达,是一个关键的问

题。在SoftEngine 里,解决这个问题的技术称为:数据安全。其中包括四个部分 :

  ·安全的任务池Safety Task Pool

  ·任务悬挂Pending

  ·降速传递Slowdown

  ·流量控制Flow control

  以下图为例描述:



    图表 9 Data-Safety

    Forward Task: 发送任务 Backward Task: 回送任务

    Undeliverable Task: 无法发送任务 Panding Task:悬挂任务

    Task Channel:任务通道 Pending Pool: 悬挂缓冲池

  ·安全的任务池Safety Task Pool

在SoftEngine 的内核,大部份对象都有自己的任务池与任务通道连接。类似于文件系统的内存缓冲,任务池对于提高系统性能有非常重要的作用。同时为了保证数据的安全不丢失,任务池需要良好的设计,包括: 过载保护(overload protection) ,硬盘缓冲等安全机制,确保无论对象运行状态如何,任务都不会丢失。也就是说,当一个任务被成功地送入目的对象的任务池,这意味着:任务是安全的。所以任务池保证了静态任务的安全性。

  ·任务悬挂Pending

在一些特殊情况下,任务无法立即发送到目的对象(如上图对象A 发送任务到对象C )。无法发送的任务将会被悬挂在一个特殊的任务池中 - 悬挂缓冲池。通过悬挂缓冲池,SoftEngine 系统会记住有那些任务因为那些目的对象而被悬挂,等待目的对象恢复后重发,或则任务超过了规定的生存周期,被丢弃。

  ·降速传递Slowdown

在常规状态下,对象A 会以最快的速度向对象B 发送任务。但如果此时,对象B 处于无效状态,或任务量过载,那么第一个无法发送的任务将会被悬挂,同时发送源对象的发送速度也会被系统自动控制,减缓发送的频率。称之为: 降速传递。

  降速传递机制可以在巨大的任务流中,有效地保护系统失去控制,尤其当某个任务流中的对象发生了意外。举个例子:

  对象A,B,C 合作完成一项任务,对象A 会产生大量的任务,经过对象B ,发送到C 。如下图:



  图表 10 One Sample

  假设,对象C 由于某种原因停止了工作,在没有降速传递机制的情况下:对象B 也会由于大量的任务没有发送,而很快"爆掉"。对象A 也会跟着失控。此时堆积在A,B,C 中间的任务将无法处理。另外,系统的CPU 、Memory 开销可以会受到影响。采用了降速传递机制,对象B 的处理和发送任务的工作在一定程度上得到控制,对象A 也是如此。整个工作流的处理速度会自动减慢。直至对象C 恢复正常的工作状态。

  所以当系统发生无法估计的问题时,降速传递可以有效地起到稳定系统的作用,避免大量数据因事故而丢失。

  ·流量控制Flow Control

在分布式系统中,任务将会通过任务通道、通讯通道在内存、网络上传输。保证传输线路上的数据安全也是非常重要了。流量控制机制是一个常见的技术用于解决传输双方的稳定及数据的安全问题。这里不做过多的介绍。



  3.5 流水线式设计模式Pipelining Design Model

  "流水线式"经常在讨论CPU 技术时被谈及。在CPU 设计中,非流水线式设计模式的问题在于:每个单元指令必须在另一个指令开始前完成。这样会有很多的空闲时间片,没有效率。而流水线式的最基本思路在于充分利用CPU 内部空闲的组件,以至于可以同时处理多了单元指令,减少空闲时间片。也就是说,单元指令之间无须等待。非常明显,这个技术可以极大程度地提高硬件效率。

  在SoftEngine 内借用了这种思路,将任务代替了指令,将功能对象代替了硬件组件。流水线式设计所运用的基本理论:将大的任务划分成一系列可交迭的、较小的任务,同时被一些功能对象分布处理。所以,在SoftEngine 基础上,应用的设计人员,需要分析应用的处理流程,在设计阶段划分大任务,提高应用系统的性能。SoftEngine 可以有效地支持这种先进的设计模式 。

  举个例子,在普通的开发设计( 非流水线式设计) 中,假设一个任务需要4 个步骤完整,

  ·第一步:保存数据到磁盘,耗时100ms

  ·第二步:从磁盘中读取历史信息,耗时20ms

  ·第三步:从内存中读取配置信息,耗时5ms

  ·第四步:结果计算,并返回结果,耗时10ms

  见下图:



  图表 11 Non-pipelining mode

  整个流程的处理时间需要135ms ,请求的返回时间也是135ms 。不难看出,第一步虽然耗时最多,但属于工作流的关键步骤,后续步骤也不等待其运行结果。而且在这个工作流中,每步操作,都需要等待上一步的操作(在同一时刻,只能有一个步骤在工作),所以135ms 不是最优化的结果。

  通过流水线式设计模式,可以进步优化。首先,将这个任务,划分为三个小任务分别由四个对象处理,所以设计了5 个对象 :

  ·对象A :划分大任务为三个小任务,同时分发。作为任务开始。

  ·对象B :保存数据到磁盘,耗时100ms

  ·对象C :从磁盘中读取历史信息,耗时20ms

  ·对象D :从内存中读取配置信息,耗时5ms

  ·对象E :等待任务2 和3 的结果,计算后返回,耗时10ms

  见下图:



  图表 12 Pipelining mode

  虽然每个步骤单位处理的时间并没有减少。但对象B 的费时操作,被安排在主要流程之外,所以没有影响整个处理时间。对象C 和D 的处理被安排在同一时刻发生。对象E 等待C 和D 的结果。所以只要工作流程为:

  (A) -> (C, D) -> (E)

步考虑任务传递时间耦合时间,及A 的分发时间,总的响应时间为:

  max( C, D ) + E = max( 20, 5 ) + 10 = 30ms

  所以,流水线式设计模式的优势,显而易见。同时也改进了以往开发流程。



  4.分布式系统对开发流程的改进



  以上介绍了分布式开发系统的关键概念及技术。利用这些技术,不但可以提高系统的性能,也可以

改进以往开发的环境和步骤。开发步骤包括以下5 步:

  ·设计Design: 改变以往从头设计的做法,主要精力集中在应用的业务流程、工作流程、任务流程的设计。不断优化流程,是应用系统成功与否的关键。

  ·定义Define: 流程确定之后,就可以从中定义出各种功能对象,服务对象,任务对象,并加以描述。此过程需要将定义的对象放入确定的流程中,模拟其使用性、有效性等 。

  ·实现Realization:开始实现定义好的的各种对象。并进行单元白盒测试,保证每个对象自身的稳定。在实现过程中会发现与定义中相矛盾的地方,此时需要与设计人员探讨修改。

  ·部署Deployment: 实现了每个对象之后,就可以对系统按照设计的流程进行部署。整个过程,都是通过配置文件进行系统调整。所以只要对象具有较强的独立性,并且保证每个对象已达到错误最小化,就可以保证在联合测试中,不会有过多的修改工作。但部署中,会根据实际境况对原先的流程进行调整,以达到最佳效果。

  ·运 行 Running: 开发的最后一步,就是进入运行状态。



  图表 13 Development process

  与传统开发流程相比,每个阶段的划分都更明确,这样有利于不同角色的划分和分工。尤其在部署阶段,原始设计人员可以使用编码完成的组件对象,直接介入系统的构建中。另外一个优势在于:整个开发周期变短。由于无需从头设计,按照一定的模式定义对象,程序的统一结构化,这些都是传统软件开发所无法比拟的。尤其充分的白盒测试,使联合测试的成功率提高,时间节省了许多 。



  5.小结



  本文,以SoftEngine 为例,简洁地介绍了,以面向对象方式,解决分布式或传统应用系统开发所需的关键技术。希望能为非Web 应用开发平台,提供一些好的体系结构,改善我们的开发环境。

  在后续文章( 应用篇) 中,将陆续结合几个实际中的案例,如:如何构建最快、最灵活、最稳定的无线数字增值服 务 ( 短信SMS, 彩信MMS ) 平台,以及相关的组件等,描述其分布式、组件化的体系,及具体的解决方案。进一步谈讨,实际应用的可操作性。



  注:

  ·在文章中所提及的一些观点,只是本人在开发中的经验所得。

  ·文章中所涉及的分布式技术,也可在SoftEngine 中得到证实 。



版权所有:UML软件工程组织