来学一学分布式系统核心:面向对象的分布式架构,分布式对象系统

本文探讨了面向对象编程在分布式系统中的应用,介绍了基于对象的分布式架构,重点分析了DCOM、CORBA和JavaRMI这三种常用的分布式对象系统,讨论了它们的原理、优点和缺点,以及在实际开发中的应用和局限性。
摘要由CSDN通过智能技术生成

面向对象的分布式架构

面向对象编程是非常流行的编程模式,因此,在分布式系统中,基于对象来设计分布式架构是自然而然的。

本章介绍面向对象的分布式架构。

基于对象的分布式架构

在基于对象的分布式系统中,对象的概念在分布式实现中起着极其关键的作用。从原理上来讲,一切都可以被作为对象抽象出来,而客户端将以调用对象的方式来获得服务和资源。

分布式对象之所以成为重要的范型,是因为它相对比较容易地把分布的特性隐藏在对象接口后面。此外,因为对象实际上可以是任何事务,所以它也是构建系统的强大范型。

面向对象技术于20世纪80年代开始用于开发分布式系统。同样,在达到高度分布式透明性的同时,通过远程计算机宿主独立对象的理念构成了开发新一代分布式系统的稳固的基础。在本节中,我们将看到基于对象的分布式系统的常用体系结构。

软件世界中的对象和现实世界中的对象类似,对象存储状态在字段(Field)里,而通过方法(Method)来暴露其行为。方法对对象的内部状态进行操作,并作为对象与对象之间通信的主要机制。隐藏对象内部状态,通过方法进行所有的交互操作,这是面向对象编程的一个基本原则——数据封装(Data Encapsulation),可以通过接口(Interface)来使用方法。一个对象可能实现多个接口,而给定的一个接口定义可能有多个对象为其提供实现。

把接口与实现这些接口的对象进行分隔,对于分布式系统是至关重要的。严格的隔离允许我们把接口放在一台机器上,而使对象本身驻留在另外一台机器上。这种组织通常称为分布式对象(DistributedObject),如图5-1所示。

图5-1 带有客户端代理的远程对象的常见组织

当客户绑定(Bind)到一个分布式对象时,就会把这个对象的接口的实现(称为代理(Proxy))加载进客户的地址空间。代理类似于RPC系统中的客户存根(Client Stub)。它所做的事是把方法调用编组进消息中,以及对应答消息进行解组,把方法调用的结果返回给客户。

实际的对象驻留在服务器计算机上,它在这里提供了与它在客户端上提供的相同的接口。进入的调用请求首先被传递给服务器存根,服务器存根对它们进行解码,在服务器中的对象接口上进行方法的调用。服务器存根还负责对响应进行编码,并把响应消息转发给客户端代理。

服务器存根通常被称为骨架(Skeleton),因为它提供了明确的方式,允许服务器中间件来访问用户定义的对象。实际上,它通常以特定语言的类的形式包含不完整的代码,需要开发人员来进一步对其进行特殊化处理。

大多数分布式对象的一个特性是它们的状态不是分布式的。状态驻留在单台机器上,在其他机器上,智能地使用被对象实现的接口,这样的对象也被称为远程对象(Remote Object)。分布式对象的状态本身可以物理地分布在多台机器上,但是这种分布对于对象接口背后的客户端来说是透明的。

常用的分布式对象系统

就目前而言,常用的分布式对象系统主要有微软DCOM(COM+)、CORBA及Java RMI。

微软DCOM

1992年4月,微软发布Windows 3.1,包括了一种称为OLE(ObjectLinking and Embedding)的机制。这个机制允许一个程序动态链接其他库来支持其他功能,例如将一个电子表格嵌入Word文档。后来,OLE演变成了COM(Component Object Model)。一个COM对象是一个二进制文件。使用COM服务的程序访问的是标准化接口的COM对象而不是其内部结构。COM对象用全局唯一标识符(GUID)来命名,用类的ID识别对象的类。可以有多种方法来创建一个COM对象,例如CoGetInstanceFromFile。COM库在系统注册表中查找相应的二进制代码(一个DLL或可执行文件)来创建对象,并给调用者返回一个接口指针。COM的着眼点在于同一台计算机上不同应用程序之间的通信需求。

DCOM(Distributed Component Object Model)是对COM的扩展,它支持不同的两台机器上的组件之间的通信,而且不论它们运行在局域网、广域网还是Internet上。借助DCOM,应用程序能够进行任意的空间分布。DCOM于1996年在Windows NT 4.0中被引入,后来更名为COM+。为了支持访问远程COM对象,DCOM需要创建一个对象的过程,此时需要提供服务器的网络名以及类ID,微软提供了一些机制来实现这一点。最透明的方式是远程计算机的名称固定在注册表(或DCOM类存储)里,与特定类ID相关联。以此方式,应用程序不知道它正在访问一个远程对象,并且可以使用与访问本地COM对象相同的接口指针。同时,应用程序也可指定一个机器名来作为参数。

由于DCOM是对COM这个组件技术的无缝升级,所以我们能够从现有的有关COM的知识中获益。以前在COM中开发的应用程序、组件、工具都可以移入分布式的环境,DCOM将屏蔽底层网络协议的细节,我们只需要集中精力于应用。

DCOM最大的缺点是,这是微软独家的解决办法,在跨防火墙方面的工作做得不是很好(大多数RPC系统也有类似的问题),因为防火墙必须允许某些端口来让ORPC和DCOM通过。

CORBA

Sun RPC、DCE等远程过程调用的机制存在一些缺陷。例如,如果服务器没有运行,客户端是无法连接到远程过程进行调用的。管理员必须确保在任何客户端试图连接到服务器之前将服务器启动。如果一个新服务或接口添加到了系统,客户端是不能发现的。最后,面向对象语言期望在函数调用中体现多态性,即不同类型的数据的函数的行为应该有所不同,而这点恰恰是传统的RPC所不支持的。

CORBA(Common Object Request Broker Architecture)就是为了解决上面提到的各种问题而产生的。CORBA是由对象管理组织(OMG)制订的一种标准的面向对象应用程序的体系规范,或者说CORBA体系结构是OMG为了解决分布式处理环境(DCE)中硬件和软件系统的互联而提出的一种解决方案。OMG成立于1989年,作为一个非营利性组织,致力于开发在技术上具有先进性、在商业上具有可行性并且独立于厂商的软件互联规范,推广面向对象模型技术,增强软件的可移植性(Portability)、可重用性(Reusability)和互操作(Interoperability)。

该组织成立之初,成员包括Unisys、Sun、Cannon、Hewlett-Packard和Philips等在业界享有盛誉的软硬件厂商,目前该组织拥有800多家成员。

CORBA体系的主要内容包括以下5个部分。

·对象请求代理(Object Request Broker,ORB):负责对象在分布环境中透明地收发请求和响应,它是构建分布对象应用、在异构或同构环境下实现应用间互操作的基础。

·对象服务(Object Services):为使用和实现对象而提供的基本对象集合,这些服务应独立于应用领域。主要的CORBA服务有:名录服务(Naming Service)、事件服务(Event Service)、生命周期服务(Life Cycle Service)、关系服务(Relationship Service)以及事务服务(Transaction Service)等。这些服务几乎包括分布式系统和面向对象系统的各个方面,每个组成部分都非常复杂。

·公共设施(Common Facilities):向终端用户提供一组共享服务接口,例如系统管理、组合文档和电子邮件等。

·应用接口(Application Interfaces):由销售商提供的可控制其接口的产品,相应于传统的应用层表示,处于参考模型的最高层。

·领域接口(Domain Interfaces):为应用领域服务而提供的接口,如OMG为PDM系统制定的规范。

当客户端发出请求时,ORB做了以下事情。

·在客户端编组参数。

·定位服务器对象。如果有必要,它会在服务器上创建一个过程来处理请求。

·如果服务器是远程的,就使用RPC或Socket来传送请求。

·在服务器上将参数解析成服务器格式。

·在服务器上组装返回值。

·如果服务器是远程的,就将返回值传回。

·在客户端对返回结果进行解析。

IDL(Interface Definition Language)用于指定类的名字、属性和方法。它不包含对象的实现。IDL编译器生成代码来处理编组、解封以及ORB与网络之间的交互。它会生成客户机和服务器存根。IDL对编程语言是中立的,支持包括C、C++、Java、Perl、Python、Ada、COBOL、Smalltalk、Objective C和LISP等语言。一个示例IDL如下。

Module StudentObject {
Struct StudentInfo {
String name;
int id;
float gpa;
};
exception Unknown {};
interface Student {
StudentInfo getinfo(in string name)
raises(unknown);
void putinfo(in StudentInfo data);
};
};

IDL数据类型如下。

·基本类型——long、short、string、float等。

·构造类型——struct、union、枚举、序列。

·对象引用。

·any类型——一个动态类型的值。

编程中最常见的实现方式是通过对象引用来实现请求。下面是一个使用IDL的例子。

Student st = ... // 获得对象的引用
try {
StudentInfo sinfo = st.getinfo("Fred Grampp");
} catch (Throwable e) {
... // 错误处理
}

在CORBA规范中,没有明确说明不同厂商的中间件产品要实现所有的服务功能,并且允许厂商开发自己的服务类型。因此,不同厂商的ORB产品对CORBA服务的支持能力不同,使我们在针对系统的待开发功能进行中间件产品选择时,有更多的选择余地。

CORBA的不足如下。

·尽管有多家供应商提供CORBA产品,但是仍找不到能够单独为一种网络中的所有环境提供实现的供应商。不同的CORBA实现之间会出现缺乏互操作性的现象,从而造成一些问题。而且,由于供应商常常会自行定义扩展,而CORBA又缺乏针对多线程环境的规范,对于像C或C++这样的语言,源代码兼容性并未完全实现。

·CORBA过于复杂,要熟悉CORBA,并进行相应的设计和编程,需要许多个月来掌握相关技术,而要达到专家水平,则需要好几年。在目前最新的Java版本中,CORBA模块已经被移除。这意味着在Java领域,将会有更多分布式技术可以用来替代CORBA。更多有关CORBA的优缺点,可以参阅Michi Henning的The rise and fall of CORBA

Java RMI

CORBA旨在提供一组全面的服务来管理在异构环境中(不同语言、操作系统、网络)的对象。Java在最初只支持通过Socket来实现分布式通信。1995年,作为Java的缔造者,Sun公司开始创建一个Java的扩展,称为Java远程方法调用(Remote Method Invocation,RMI)。JavaRMI允许程序员在创建分布式应用程序时,可以从其他Java虚拟机调用远程对象的方法。

一旦应用程序(客户端)引用了远程对象,就可以进行远程调用了。这时通过RMI提供的命名服务(RMI注册中心)来查找远程对象,接收作为返回值的引用。Java RMI在概念上类似于RPC,但能在不同地址空间支持对象调用的语义。

与大多数其他诸如CORBA的RPC系统不同,RMI只支持基于Java来构建,但也正是这个原因,RMI对于语言来说更加整洁,无须做额外的数据序列化工作。Java RMI的设计目标包括以下几点。

·能够适应语言,集成到语言,易于使用。

·支持无缝的远程调用对象。

·支持服务器到applet的回调。

·保障Java对象的安全环境。

·支持分布式垃圾回收。

·支持多种传输。

分布式对象模型与本地Java对象模型的相似点在于以下几点。

·引用一个对象可以作为参数传递或作为返回的结果。

·远程对象可以投到任何使用Java语法实现的远程接口的集合上。

内置Java instanceof操作符可以用来测试远程对象是否支持远程接口。不同点有以下几点。

·远程对象的类是与远程接口进行交互,而不是与这些接口的实现类交互。

·Non-remote参数对于远程方法调用来说是通过复制,而不是通过引用来传递的。

·远程对象是通过引用来传递的,而不是复制实际的远程对象实现。

·客户端必须处理额外的异常。

1.接口和类

所有的远程接口都继承自java.rmi.Remote接口。例如:

public interface bankaccount extends Remote
{
public void deposit(float amount)
throws java.rmi.RemoteException;
public void withdraw(float amount)
throws OverdrawnException,
java.rmi.RemoteException;
}

注意,每个方法必须在throws里面声明java.rmi.RemoteException。只要客户端调用远程方法出现失败,这个异常就会抛出。

2.远程对象类


Java.rmi.server.RemoteObject类提供了远程对象实现的语义,包括hashCode、equals和toString。java.rmi.server.RemoteServer及其子类让远程对象实现可见。java.rmi.server.UnicastRemoteObject类定义了客户端与服务器对象实例并建立一对一的连接。

3.存根

Java RMI通过创建存根方法来工作。存根由rmic编译器生成。自Java 1.5以来,Java支持在运行时动态生成存根类。编译器rmic会提供各种编译选项。

4.定位对象

引导名称服务提供了用于存储对远程对象的命名引用。一个远程对象引用可以存储使用类java.rmi.Naming提供的基于URL的方法。例如:

BankAccount acct = new BankAcctImpl();
String url = "rmi://java.sun.com/account";
// 绑定URL到远程对象
java.rmi.Naming.bind(url, acct);
// 执行lookup方法
acct = (BankAccount)java.rmi.Naming.lookup(url);

Java RMI的工作流程如图5-2所示。

图5-2 Java RMI的工作流程

5.RMI架构

Java RMI是一个三层架构(见图5-3),最上面是Stub/Skeletonlayer(存根/骨架层)。方法调用从Stub、Remote Reference Layer(远程引用层)和Transport Layer(传输层)向下传递给主机,然后再次经过Transport Layer层,向上穿过Remote Reference Layer和Skeleton,到达服务器对象。Stub扮演着远程服务器对象的代理的角色,使该对象可被客户激活。Remote Reference Layer处理语义、管理单一或多重对象的通信,决定调用是发往一个服务器还是多个。Transport Layer管理实际的连接,并且追踪可以接收方法调用的远程对象。服务器端的Skeleton完成对服务器对象实际的方法调用,并获取返回值。返回值向下经RemoteReference Layer、服务器端的Transport Layer传递回客户端,再向上经Transport Layer和Remote Reference Layer返回。最后,Stub程序获得返回值。

图5-3 Java RMI架构

要完成以上操作需要有以下几个步骤。

·生成一个远程接口。

·实现远程对象(服务器程序)。

·生成Stub和Skeleton(服务器程序)。

·编写服务器程序。

·编写客户端程序。

·注册远程对象。

·启动远程对象。

6.RMI分布式垃圾回收

根据Java虚拟机的垃圾回收机制原理,在分布式环境下,服务器进程需要知道哪些对象不再由客户端引用,从而可以被删除(垃圾回收)。在JVM中,Java使用引用计数。当引用计数归零时,对象将会被垃圾回收。在RMI中,Java支持两种操作——dirty和clean。本地JVM定期发送一个dirty到服务器来说明该对象仍在使用。定期重发dirty的周期是由服务器租赁时间来决定的。当客户端不需要更多的本地引用远程对象时,它发送一个clean调用给服务器。不像DCOM,服务器不需要计算每个客户机使用的对象,只是简单地做下通知。如果它租赁时间到期之前没有接收到任何dirty或者clean的消息,则可以安排将对象删除。

分布式对象系统优缺点

从5.2节的学习,我们了解到分布式对象系统的优点及缺点。

分布式对象系统的主要优点是支持面向对象编程。在面向对象编程大行其道的今天,毫无疑问,采用面向对象的方式来开发分布式系统是最容易被开发者接受的。

当然,分布式对象系统也有不足之处。

·只支持针对特定的平台。以微软DCOM(COM+)、Java RMI为例,这些分布式对象系统只能在特定的平台上才能使用,比如微软DCOM(COM+)只能在微软的操作系统下才能使用,而RMI只能在Java平台上使用。

·规范复杂,实现困难。典型的例子是CORBA,虽然CORBA的贵范非常完善,也号称支持跨平台,但允许CORBA本身的复杂性,导致了厂商在实现CORBA时产生了非常大的差异,造成不同的CORBA实现之间会出现缺乏互操作性的现象。同时,CORBA过于复杂,导致能很好使用CORBA的人很少。这也是CORBA无法继续流行的原因。

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值