26、CORBA 与 DSA:分道扬镳还是携手共进?

CORBA 与 DSA:分道扬镳还是携手共进?

在分布式系统编程领域,有两种重要的技术值得深入探讨,它们分别是 CORBA(Common Object Request Broker Architecture)和 DSA(Distributed Systems Annex)。下面将详细介绍这两种技术,并对它们进行比较。

分布式语言的运用

传统上,人们可能会定义像 IDL(Interface Definition Language)这样的新语言来实现分布式系统。但另一种思路是对现有编程语言进行扩展,使其具备分布式特性。分布式对象范式为分布式系统编程提供了更面向对象的方法。分布式对象是抽象数据类型的扩展,它允许在类型接口中提供的服务被调用,而无需考虑实际服务的执行位置。当与继承和多态等面向对象特性结合时,分布式对象为分布式应用程序营造了更具动态性和结构化的计算环境。

例如,Ada 95 包含了分布式系统附件(DSA),它定义了多个扩展,允许用户完全用 Ada 编写分布式系统。用户可以使用包来定义分布式对象上的远程过程调用或远程方法调用。Ada 95、Java/RMI 和 Modula - 3 的分布式系统模型非常相似,它们都用语言的子集替代了 IDL。这种语言能透明地支持远程过程调用和远程对象方法调用。

使用这种语言编写的程序通常与使用相同语言编写的程序进行通信。不过,这种限制也带来了一些好处,因为语言不受所有宿主语言可用的最小公共特性子集的约束,所以能提供更强大的功能。在 Ada 95 中,用户定义远程服务的规范并实现它们,就像实现普通的非分布式服务一样。Ada 95 环境会对其进行编译,生成存根文件和骨架文件,这些文件会自动包含对实际服务体的调用。由于语言环境能完全控制开发过程,创建对象、获取或注册对象引用以及使对象骨架适应用户对象实现等操作都是透明的。

DSA 与 CORBA 的比较
DSA 概述

Ada 分布式系统附件为分布式系统编程提供了解决方案。Ada 应用程序可以被分区,以便在计算机网络上执行,这样类型化对象可以通过远程子程序调用进行引用。在被归类为远程调用接口(RCI)或远程类型(RT)的库单元中声明的远程调用子程序可以是静态绑定或动态绑定的,这使得应用程序可以使用以下经典范式之一:
- 远程子程序 :对于程序员来说,远程子程序调用类似于常规子程序调用。使用子程序访问类型的运行时绑定也可用于远程子程序。
- 分布式对象 :可以定义特定的访问类型来指定远程对象。当对由远程访问指定的对象调用原始调度操作时,会在创建该对象的分区上透明地执行远程调用。
- 共享对象 :数据可以在活动分区之间共享,提供类似于共享内存、共享文件系统或数据库的存储库。无入口受保护对象允许对共享对象进行安全访问和更新。此功能与分布式对象的概念相互独立,分布式对象只能通过导出的服务进行访问。

一个 Ada 95 分布式应用程序是一组在一台或多台机器上并发执行的分区;每个分区由一个或多个编译单元组成,这些编译单元共同构成一个可执行二进制文件。

下面是 DSA 架构的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(Processing Node 1):::process -->|Network| B(Processing Node 2):::process
    A -->|Data| C(Storage Node):::process
    B -->|Data| C
    A1(Unit_2):::process --> A
    A2(Unit_3):::process --> A
    B1(Unit_2):::process --> B
    B2(Unit_3):::process --> B
    C1(Unit_1):::process --> C
    C2(Data_1):::process --> C
    C3(Data_3):::process --> C
CORBA 概述

CORBA 是一项由行业支持的工作,旨在通过 CORBA 接口定义语言(IDL)对分布式对象范式进行标准化。IDL 的使用使 CORBA 比其他任何客户端/服务器中间件更具自描述性。CORBA 的主要特性包括接口定义语言、语言映射、存根、骨架和对象适配器、ORB(Object Request Broker)、接口存储库、动态调用、ORB 协议和 CORBA 服务。

IDL 用于指定模块、常量、类型和接口。对象接口定义了客户端可以调用或访问的操作、异常和公共属性。CORBA 仅基于分布式对象提供模型。在某些方面,它可以与 Java 相比较,因为 Java 只提供面向对象的编程模型,而忽略了经典的结构化编程模型。

IDL 翻译器会在宿主语言(如 C++、C、Java、Ada 95)中生成客户端存根和服务器骨架。语言映射规定了如何在宿主语言中实现 IDL 实体。根据宿主语言可用的特性,映射的难易程度会有所不同。当 IDL 特性在宿主语言中未定义时,映射会提供一种标准化但复杂的方式来模拟缺失的特性。

下面是 CORBA 架构的 mermaid 流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    A(Client - language A):::process -->|IDL specification| B(IDL Stubs):::process
    B -->|Requests| C(ORB):::process
    C -->|Requests| D(IDL Skeleton):::process
    D -->|Requests| E(Object Implementation - language B):::process
    F(Dynamic Invocation):::process --> C
    G(CORBA Bus):::process --> C
接口定义语言
  • DSA 中的 IDL :在 DSA 中,IDL 是 Ada 95 的子集。用户在编译时识别接口包。一些库级包通过编译指示进行分类:
    • 远程调用接口(RCI) :使用此编译指示分类的库单元可以声明要远程调用和执行的子程序。这种 RPC 操作是静态绑定的操作。在这些单元中,客户端和服务器不共享内存空间。动态绑定调用与 Ada 解引用子程序(远程子程序访问 - RAS)和对类宽操作数进行调度(类宽类型的远程访问 - RACW)的能力集成。这些远程访问类型可以在 RCI 包中声明。
    • 远程类型(RT) :与 RCI 单元不同,使用此编译指示分类的库单元可以定义分布式对象及其远程方法。它们还可以定义上述远程访问类型。在 RT 单元中定义的子程序不是远程子程序。与 RCI 单元不同,RT 单元不必只放在一个分区上,它们的行为类似于常规单元。
    • 共享被动(SP) :在此类库单元中声明的实体将被映射到共享地址空间(文件、内存或数据库)。当两个分区使用这样的库单元时,它们可以通过读写公共变量进行通信,这对应于共享变量范式。在这些单元中声明的无入口受保护对象提供对共享数据的原子访问,类似于事务处理。

在 RT 或 RCI 单元中,禁止使用变量,并且仅在提供其编组子程序的情况下才允许使用非远程访问类型。在远程方法或子程序调用中引发的任何异常都会传播给调用者。在 RCI 单元中,额外的编译指示 All Calls Remote 可以强制远程过程调用通过通信子系统路由,即使是本地调用也是如此,这有助于在接近分布式情况的非分布式环境中调试应用程序。编译指示 Asynchronous 允许静态和动态绑定的远程调用异步执行。异步过程不会等待远程调用完成,而是让调用者继续其执行路径。该过程必须仅具有输入或访问参数,并且在远程过程执行期间引发的任何异常都会丢失。

所有这些分类单元都可以是通用的。这些通用包的实例可以分类,也可以不分类。如果不分类,单元将失去其分类属性。每个分类编译指示都有非常具体的依赖规则,一般规则是 RCI ≻ RT ≻ SP ≻ Pure ,这意味着远程类型包声明只能依赖于其他远程类型、共享被动和纯单元。

以下是一个完整的 DSA 示例代码:

-- (b) Generic remote unit
with Storage; use Storage;
generic
package Factory is
   pragma Remote_Call_Interface;
   procedure Notify (Q : Integer);
   pragma Asynchronous (Notify);
end Factory;

-- (c) First generation worker
with Types, Storage; use Types, Storage;
package One_Worker is
   pragma Remote_Types;
   type G1_Worker is
      new Worker with private;
   procedure Assign
     (W : access G1_Worker;
      Q : Integer;
      N : Notify);
private
   -- Declaration not shown
end One_Worker;

-- (d) Shared memory data
package Storage is
   pragma Shared_Passive;
   protected Queue is
      procedure Save (Q, R : Integer);
      procedure Load
        (Q : in Integer;
         R : out Integer);
   private
      -- Declaration not shown
   end Queue;
end Storage;

-- (e) Second generation worker
with Types, Storage; use Types, Storage;
with One_Worker; use One_Worker;
package Another_Worker is
   pragma Remote_Types;
   type G2_Worker is
      new G1_Worker with private;
   procedure Assign
     (W : access G2_Worker;
      Q : Integer;
      N : Notify);
private
   -- Declaration not shown
end Another_Worker;

-- (f) Several DSA features
with Storage; use Storage;
package Types is
   pragma Remote_Types;
   type Notify is
      access procedure (Q : Integer);
   pragma Asynchronous (Notify);
   type Worker is
      abstract tagged limited private;
   procedure Assign
     (W : access Worker;
      Q : in Integer;
      N : in Notify) is abstract;
   type Any_Worker is
      access all Worker'Class;
   pragma Asynchronous (Any_Worker);
private
   -- Declaration not shown
end Types;

-- (g) Static and unique workers pool
with Types; use Types;
package Workers is
   pragma Remote_Call_Interface;
   procedure Free (W : in  Any_Worker);
   procedure Hire (W : out Any_Worker);
end Workers;

-- (h) Remote unit instantiation
with Factory;
package One_Factory is new Factory;
pragma Remote_Call_Interface (One_Factory);
  • CORBA 中的 IDL :在 CORBA 中,IDL 是一种描述性语言,它支持 C++ 语法来声明常量、类型和操作。从 IDL 描述中,翻译器可以生成客户端头文件和服务器实现骨架。

IDL 文件首先定义一个模块,它提供一个命名空间来收集一组接口,这是引入层次结构的一种方式,其指定形式类似于 <module>::<interface>::<operation> 。Ada 95 绑定将此元素映射到一个(子)包。 #include 语句使任何其他命名空间可见。

模块可以定义接口。接口定义了客户端可以在对象上调用的一组方法,还可以定义异常和属性。异常类似于 C++ 异常,可以附加一个数据组件;属性是一个组件字段。对于每个属性,实现会自动创建 Get Attribute Set Attribute 子程序,对于只读属性仅提供 Get 。接口可以从一个或多个接口派生(多重继承)。

Ada 95 绑定将此元素映射到一个包或子包。对于客户端存根,实现会自动在与接口名称匹配的包中创建一个名为 Ref 的标记类型(它派生自 CORBA.Object.Ref 或在另一个接口中定义的另一个 Ref 类型)。对于服务器骨架,实现会自动在名为 Impl 的包中创建一个名为 Object 的标记类型(它派生自实现定义的私有标记类型 Object ), Impl 是一个以接口名称命名的包的子包。

方法由唯一名称(不允许重载)及其签名(其形式参数的类型)定义。每个参数可以是 in out inout 模式,其含义与 Ada 中的同名模式类似。方法可能引发的每个异常也必须作为方法签名的一部分进行声明。

oneway 属性可以应用于子程序,使其具有最多一次语义,而不是默认的恰好一次语义。这使得方法不能有输出参数、返回值或引发异常。假设调用者在发送输入参数后恢复执行是不可移植的。

大多数 CORBA 数据类型可以直接映射到预定义的 Ada 类型,但 any sequence 除外。 any 可以指定任何 CORBA 类型,它被映射到具有读写操作的流类型。 sequence 包含给定类型的项目列表,在 Ada 中使用一对冗长的通用包表示。需要注意的是,CORBA 字符串类型被映射到 Ada 95 的无界字符串类型。IDL 不提供无约束数组的等效物。

Ada 95 映射提供了特殊机制来实现两个难以映射的 CORBA 特性。首先,它提供了多重继承的翻译。如前所述,Ada 95 包定义了一个从第一个接口派生的类型,并扩展其原始操作列表以实现从其他接口的继承(此解决方案与混入类似)。另一个对 Ada 程序员来说不自然的 CORBA 特性来自前向声明。在 Ada 中,两个包规范不能相互 with ,但在两个 IDL 接口之间可能会出现这种情况。为了解决这个问题,映射建议创建 “前向” 包,这可能会导致一种非常不直观的情况,即客户端存根不 with 其通常的接口包,而是 with “前向” 包。

当使用 CORBA 开发分布式应用程序时,可能会出现两种情况。在服务器端,程序员负责 IDL 文件。他必须理解 Ada 95 语言映射,以便尽可能避免具有非平凡实现的结构,如前向声明和多重继承。在服务器和客户端,程序员都必须处理生成的代码。良好理解映射有助于在 IDL 文件和生成的代码之间来回切换,以便全面了解分布式应用程序。根据宿主语言的不同,理解这种映射可能是一项繁琐的任务。

IDL 接口信息可以在线存储在一个名为接口存储库(IR)的数据库中。CORBA 规范描述了接口存储库的组织方式以及如何从中检索信息。接口存储库允许客户端发现它在编译时不知道的方法的签名,然后可以使用该知识和方法参数的值来构造完整的请求并调用该方法。允许在运行时构造方法调用请求的一组函数是动态调用接口(DII)。

IR API 允许客户端探索存储库类以获得模块定义树。从这棵树中,客户端提取定义常量、类型、异常和接口的子树。从接口子树中,客户端可以选择一个操作及其参数列表(类型、名称和模式)和异常。

客户端有三种发出请求的方式。与静态情况一样,他可以发送请求并等待结果;也可以进行单向调用并丢弃结果。对于动态请求,还提供了第三种机制:客户端可以发送请求而不等待结果,稍后异步获取结果。

DII 在服务器端有一个对应的部分,称为动态骨架接口。这两种机制都很强大,但使用起来非常复杂和繁琐。在某些方面,它们也违反了 Ada 95 的哲学,因为没有保留强类型。大多数用户将继续使用静态调用。

通信子系统

通信子系统是分布式系统的关键要点之一,它提供基本服务,如将消息从分布式程序的一部分传输到另一部分的能力。这些基本服务随后被更高级别的服务用于构建功能齐全的分布式系统。

有时很难界定通信子系统和外部服务的界限。此外,在 CORBA 中被视为服务的东西在 DSA 中可能被视为纯粹的内部服务。

在 DSA 中,编译器在分布式方面未完成的所有工作都属于分区通信子系统(PCS)。例如,确定将被远程调用的包所在的分区是 PCS 的责任。

PCS 的入口点在 DSA 中定义明确,并在 System.RPC 包声明中进行了描述。通过查看这个包,可以注意到没有与远程子程序调用中止相关的内容,尽管附件规定如果这样的调用被中止,必须向远程分区发送中止消息以取消远程处理。这意味着 PCS 负责检测对其入口点之一的调用已被中止,并必须在没有编译器帮助的情况下发送这样的中止消息。

PCS 的另一个有趣特性是它对未知异常的处理方式。当远程子程序调用执行引发异常时,异常会传播回调用者。然而,调用者可能对异常声明没有任何可见性,但仍可以使用 when others 子句捕获它。但如果调用者不捕获它并让它向上传播(可能在另一个分区中),情况就会变得复杂。

综上所述,DSA 和 CORBA 在分布式系统编程中各有特点。DSA 基于 Ada 95 语言扩展,提供了与语言紧密结合的分布式编程能力,而 CORBA 通过 IDL 实现了跨语言的分布式对象通信。在选择使用哪种技术时,需要根据具体的应用场景、编程语言偏好以及系统的复杂度等因素进行综合考虑。

CORBA 与 DSA:分道扬镳还是携手共进?(续)

技术点分析与对比
语言层面对比
对比项 DSA CORBA
IDL 性质 Ada 95 的子集 独立的描述性语言
绑定方式 静态绑定或动态绑定,通过 Ada 自身能力集成 依赖语言映射将 IDL 实体映射到宿主语言
多重继承处理 无特殊处理 Ada 95 映射提供特殊机制实现
前向声明处理 无此问题 Ada 95 映射通过创建“前向”包解决

从语言层面来看,DSA 与 Ada 95 紧密结合,利用语言自身特性实现分布式编程,而 CORBA 的 IDL 更具通用性,但在映射到宿主语言时可能会遇到一些复杂问题。

接口定义对比
  • DSA 接口 :通过编译指示对不同类型的接口进行分类,如 RCI、RT 和 SP,每种类型有不同的功能和使用规则。接口定义与 Ada 95 的语法和特性紧密相关,便于 Ada 程序员理解和使用。
  • CORBA 接口 :使用模块和接口的层次结构,接口可以定义方法、异常和属性,支持多重继承。Ada 95 绑定会自动生成特定的标记类型,增加了代码的复杂性,但也提供了更灵活的对象引用和操作方式。

以下是 DSA 和 CORBA 接口定义的 mermaid 对比流程图:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
    subgraph DSA
        A(RCI):::process -->|静态绑定| B(远程子程序):::process
        C(RT):::process -->|定义| D(分布式对象):::process
        E(SP):::process -->|共享| F(共享对象):::process
    end
    subgraph CORBA
        G(Module):::process -->|包含| H(Interface):::process
        H -->|定义| I(Methods):::process
        H -->|定义| J(Exceptions):::process
        H -->|定义| K(Attributes):::process
    end
通信子系统对比
  • DSA 通信子系统(PCS) :负责编译器未处理的分布式相关工作,如确定远程调用包的分区位置。入口点明确,但对远程调用中止和未知异常的处理需要自身额外处理。
  • CORBA 通信子系统 :通过 ORB 实现消息传输,IDL 翻译生成的存根和骨架文件与 ORB 交互。提供动态调用接口(DII)和动态骨架接口,增加了通信的灵活性,但使用复杂。
实际应用场景分析
DSA 适用场景
  • 基于 Ada 95 开发的系统 :如果项目已经使用 Ada 95 进行开发,DSA 可以无缝集成到现有代码中,利用 Ada 95 的强类型和结构化编程优势,实现分布式功能。
  • 对系统安全性和可靠性要求高的场景 :DSA 的强类型检查和异常处理机制可以保证系统的稳定性,无入口受保护对象对共享对象的安全访问和更新功能,适用于航空航天、国防等对安全性要求极高的领域。
CORBA 适用场景
  • 跨语言开发的分布式系统 :CORBA 的 IDL 可以支持多种宿主语言,如 C++、Java、Ada 95 等,适合不同团队使用不同语言开发的大型分布式项目。
  • 需要动态发现和调用服务的场景 :接口存储库和动态调用接口(DII)允许客户端在运行时发现和调用未知的服务,适用于服务频繁变化或需要灵活扩展的系统。
操作步骤总结
使用 DSA 开发分布式系统的步骤
  1. 定义接口包 :根据需求使用编译指示将库单元分类为 RCI、RT 或 SP。
    • 示例代码中, Factory 包使用 pragma Remote_Call_Interface 分类为 RCI 包。
  2. 实现子程序和对象 :在相应的包中实现远程子程序、分布式对象或共享对象。
    • One_Worker 包定义了 G1_Worker 类型和 Assign 子程序。
  3. 编译和部署 :使用 Ada 95 编译器编译代码,生成存根文件和骨架文件,将分区部署到不同的机器上。
使用 CORBA 开发分布式系统的步骤
  1. 编写 IDL 文件 :定义模块、接口、方法、异常和属性。
    • 例如,定义一个包含 HelloWorld 接口的 IDL 文件。
  2. 生成代码 :使用 IDL 翻译器根据语言映射生成客户端存根和服务器骨架文件。
    • 如使用 Ada 95 绑定生成相应的 Ada 代码。
  3. 实现服务 :在服务器端实现接口定义的方法,在客户端调用这些方法。
    • 服务器端实现 HelloWorld 接口的具体方法,客户端调用该方法获取服务。
  4. 配置和部署 :配置 ORB 和相关环境,将服务器和客户端程序部署到不同的机器上。
总结与展望

DSA 和 CORBA 作为两种不同的分布式系统编程技术,各有其优势和适用场景。DSA 与 Ada 95 紧密结合,提供了简洁、安全的分布式编程方式;CORBA 通过 IDL 实现了跨语言的分布式对象通信,具有更高的灵活性和通用性。

在未来的分布式系统开发中,开发者可以根据项目的具体需求选择合适的技术。同时,随着技术的不断发展,可能会出现将两者优势结合的新方法,以满足更复杂、多样化的分布式应用需求。例如,在某些对安全性要求高且需要跨语言交互的系统中,可以探索如何在 DSA 的基础上引入 CORBA 的部分特性,实现更强大的分布式功能。

总之,无论是 DSA 还是 CORBA,它们都为分布式系统编程提供了重要的技术支持,在不同的领域发挥着重要作用。开发者需要深入理解它们的特点和差异,才能在实际项目中做出更合适的选择。

采用PyQt5框架Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层和用户界面层。数据持久化方案支持SQLite轻量级数据库MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值