`
amanhu
  • 浏览: 12375 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

RMI 基础

 
阅读更多

原文地址:jGuru: Remote Method Invocation (RMI)

如果您本文的翻译有任何建议,请留言。

这篇文章讲述Java2 平台中远程方法调用(RMI)技术的基础。

简介:使用RMI进行分布式计算

RMI(Remote Method Invocation,远程方法调用),在JDK1.1中被首次引入,它将网络编程提升到一个更高的层面。尽管相对来说,RMI比较易用,它仍然是一个引人注目的强大技术。它为普通的java开发者揭开了一个全新的角度——分布式对象计算的世界。

这篇文章将对这个通用的技术作一个深度的介绍。RMI技术被认为形成于JDK1.1,在Java 2 SDK中得到显著提升。在应用时,RMI在这两个版本中的不同点将会予以指明。

目标

RMI的设计者而言,首要目标就是:允许程序员在开发分布式Java程序和非分布式程序时使用的语法和语义。为了做到这一点,他们的必须小心的将Java类和对象在单个JVM中的工作模型映射到分布式计算环境(多个JVM)中Java类和对象的新工作模型。

本节从分布式或远程Java对象的角度来介绍RMI框架,并分析它们与本地Java对象的行为上的不同。RMI框架定义了对象如何执行逻辑,异常何时和怎样发生,内如如何管理,和参数如何传递给远程方法,并获取返回值。

对比:分布式程序和非分布式程序

RMI架构力图使分布式Java对象与本地Java对象的使用方式相类似。虽然设计者成功的实现了这一点,但是仍有一些重要的不同点,如表所示:

即使你无法理解表中的所有不同点,也不必担心。但你分析RMI架构的时候,这些会变得清晰。你可以把这张表当作你学习RMI时的参考。

本地对象

远程对象

对象定义

本地对象由一个Java类定义

远程对象的外在行为由一个继承自Remote接口的接口定义。

对象实现

本地对象由它的Java类所实现

远程对象的行为由一个实现了Remote接口的Java类执行

对象创建

使用new运算符创建本地对象的一个新实例

在远程主机上使用new运算符创建一个远程对象的新实例。客户端不能直接创建远程对象(除非使用Java 2 的远程对象激活)

对象访问

本地对象可以使用对象引用直接访问

远程对象的访问,则需要使用一个指向代理对象(proxy stub)的引用,这个代理对象实现了远程接口。

引用

在单JVM中,一个对象引用直接指向JVM堆中一个对象。

“远程引用”是本地JVM堆中的代理对象的引用。这个代理对象包含一些信息,这些信息使得代理对象可以与远程对象进行交互。远程对象包含对应方法的实现。

终结化(Finalization)

如果一个对象实现了finalize()方法,在被垃圾回收器回收前,finalize()方法会被调用。

如果一个对象实现了unreferenced接口,在所有的远程引用断开时,接口中unreferenced方法会被调用。

垃圾回收

当对象的所有本地引用断开后,对垃圾回收器而言,该对象可回收。

分布式的垃圾回收器和本地垃圾回收器器共同工作。如果没有远程引用,并且所有远程对象的本地引用都断开了,那么对垃圾回收器而言,它可以通过正常的方式回收。

异常

要么是运行时异常,要么是编译时异常。Java编译器要求所有程序处理所有的编译时异常。

RMI迫使程序处理任何可能抛出的RemoteException 对象。这是为了保证分布式应用程序的健壮性。

Java RMI架构

RMI架构的设计目标是创建一个Java分布式对象模型,使之与Java编程语言和本地对象模型自然的集成。RMI架构成功了。针对分布式计算世界,它创建了一个系统。该系统继承了Java架构的安全性和健壮性。

接口:RMI的核心

RMI架构基于一个重要的原则:行为的定义和行为的实现是相互独立的概念。RMI允许行为定义的代码和行为的实现代码相分离和运行在各自独立的JVM中。

该原则很好的符合分布式系统的要求。在分布式系统中,客户端只关心服务的定义,服务端则关注服务的提供。

特别的,在RMI中,远程服务被定义在Java接口中;而远程服务的实现则在类中。因此,接口定义行为,类则定义行为的实现。理解RMI的关键是记住这一点。

下图说明了这种相互独立。

记住,Java接口并不包含运行的代码。RMI支持两个实现相同接口的类。第一个是行为的实现,它运行在服务端,第二个类作为远程服务的代理在客户端运行。如下图所示。

客户端程序通过代理对象调用服务方法,RMI将请求发送给远程JVM,然后将请求交给实现。实现提供的返回值被送回给代理,然后交给客户端程序。

RMI层级架构

在对RMI架构的上层理解后,来看看上层覆盖之下的底层实现吧。

RMI的实现本质上构建了三个抽象层。第一层是桩和框架层(the Stub and Skeleton layer),它正好位于开发者的视角之下。当客户端调用接口中定义的方法时,这一层拦截该方法调用并重定向到一个远程的RMI服务。

下一层是远程引用层。这一层知道如何拦截并管理远程服务对象的引用,这些引用由客户端创建。在JDK1.1中,这一层连接客户端和在服务器上运行的远程服务对象。该连接是一个一对一的连接。在Java 2 开发工具包中,这一层得到了强化,通过远程对象激活(Remote Object Activation),使其支持对处于休眠状态的远程服务对象的激活。

传输层是基于在一个网络中机器间的TCP/IP连接。它提供基本的连接以及一些防火墙穿透策略。

采用层级架构,可以在不影响系统其他部分的情况下,加强或替换某一层。例如,传输层可以使用UDP/IP协议替代,而无需影响上层。

桩和框架层(Stub and Skeleton Layer)

RMI的桩和框架层正好处于Java开发者的视线之下。在这一层,RMI使用了GOF的《设计模式》中的代理设计模式。在代理设计模式中,一个上下文中的对象是另一个上下文中对象的代理。代理对象在参与的对象间转寄方法调用。下图是代理模式的说明。

对于代理模式,在RMI中的运用,桩类(stub)代表代理,远程服务实现类代表真实对象(RealSubject)

框架就是为使用RMI而产生的一个帮助类。框架知道如何通过RMI连接与桩类通信。框架会和桩进行会话。它读取来自连接的方法调用中的参数,调用远程服务实现对象,接受返回值,然后将返回值回写到给Stub对象。

RMIJava 2 SDK实现中,新的线协议废弃了框架类。RMI使用反射来产生对远程服务对象的连接。只有在JDK1.1或兼容JDK1.1的系统实现中,你才需要考虑框架类和对象。

远程引用层

远程引用层定义并支持对RMI连接的语义级调用。这一层提供一个远程引用对象。该对象代表了对远程服务实现对象的连接。

桩对象使用调用RemoteRefinvoke()方法转寄方法调用。远程引用对象对远程服务进行语义级的调用。

RMIJDK1.1实现版本中,只给客户端提供了一种连接到远程服务对象的方法:单向传播的、点对点的连接。在远程服务能被客户端使用之前,它必须在服务器上被实例化,并导出到RMI系统中(如果是首选服务,他必须命名并在RMI注册器上注册)。

RMIJava2 SDK实现版本为客户-服务器连接增加了一个新的语义。在这个版本中,RMI支持可激活的远程对象。为了(调用)可激活的对象(的服务方法),客户端对代理产生一个方法调用,RMI根据远程对象是否处于休眠状态作出决定。如果它处于休眠状态,RMI将实例化这个对象,并从硬盘文件中恢复它的状态。一旦可激活对象加载到内存中,它就如同JDK1.1版本中的远程服务实现对象。

其它类型的连接在语义上是可能的。例如,采用多路广播,单个代理能同时将方法请求发给多个实现,并接受第一个回复(这勊改善相应时间,或许还可以改善可用性)。在将来,Sun会给RMI增加更多的语义调用。

传输层

传输层产生JVM间的连接。所有的连接都是基于流的网络,并采用TCP/IP

即使是运行在同一个物理主机的两个JVM,它们之间仍然通过主机的TCP/IP协议栈进行通信(这是为什么如果你要运行本课的练习,在你的电脑上必须有一个可用的TCP/IP配置)。下图显示了在JVMTCP/IP的自由使用。

正如你所知,在两台基于IP地址和端口号的主机间,TCP/IP提供持久的、基于流的连接。通常情况下,我们使用域名来代替IP地址。这意味着谈论flicka.magelang.com:3452rosa.jguru.com:4432间的TCP/IP连接接。

TCP/IP的顶端,RMI使用一个称为JRMP(Java Remote Method Protocol)的线级协议。JRMP是一个专有的,基于流的协议。目前,JRMP被部分地在两个版本中详细说明。RMI的第一个版本随着JDK1.1一起发布的,需要在服务器上使用框架类;第二个版本随着Java 2 SDK一起发布的。它在性能上得到优化,并无需框架类。(需要指出的是:一些可选的实现,例如BEA Weblogic NinjaRMI并不使用JRMP,取而代之的是他们字节线级协议。“对象空间公司(ObjectSpace,一个软件公司)”的航海者(Voyager,该公司的产品)识别JPMP,可以在线级协议上与RMI进行交互。)

SUNIBM联合致力于下一版的RMI,称为RMI-IIOP,它将会出现在Java 2 SDK 1.3中。关于RMI-IIOP,最有趣的事情是:在客户端和服务器通信时,它采用OMG(Obeject Management Group)的互联网内部对象请求代理协议(Internet Inter-ORB Protocol)取代JRMP协议。OMG是一个有800多名会员的组织,它定义了一个厂商中立的,分布式对象架构,叫做公共对象请求代理体系架构(CORBACommon Object Request Broker Architecture)CORBA的对象请求代理客户端和服务器端采用IIOP进行通信。随着CORBA的对象传值扩展和从Java语言到接口定义语言(IDL, Interface Description Language)的映射的采用,为直接将RMICORBA集成的基础工作宣告完成。新版的RMI-IIOP实现支持大部分的RMI特性集,除了:

  • Java.rmi.server.RMISocketFactory
  • UnicastRemoteObject
  • Unreferenced
  • The DGC interfaces
<!--[if !supportLists]-->

RMI传输层的设计,是为了创建客户端和服务器端的连接,即使是在面临网络障碍的时候。

在一个客户端和服务器间,尽管传输层更喜欢使用多个TCP/IP连接,但是某些网络配置只允许使用单个TCP/IP连接(对于小程序(applet),一些浏览器只允许它和主机服务器间使用单个网络连接)。

在这种情况下,传输层使用单个TCP/IP连接,采用多路传输的方式虚拟多个连接。

远程对象命名

在展示RMI架构的时候,有一个问题被多次跳过,那就是:客户端如何找到RMI远程服务。现在,你会找到这个问题的答案。通过使用命名和目录服务,客户端才能找到远程服务。这看起来像个循环逻辑。一个客户端如何能通过使用一个服务来定位另一个服务。事实上,情况就是这样。一个命名和目录服务运行在一个广为人知的主机和端口上。

(广为人知,意味着在组织中的每个人都知道那是什么)。

RMI可以使用许多不同的目录服务,包括Java命名和目录接口(JNDI)RMI本身包括一个叫做RMI注册器的简单服务,rmiregistryRMI注册器运行在每一台机器上,默认使用1099端口,持有远程服务对象并接受查询。

使用RMI

现在,是时候构建一个可运行RMI系统了,从而获得一些亲身体验。在这一节,你将构建一个简单的远程计算服务,并通过客户端程序使用它。

一个可运行的RMI系统有以下几部分构成:

  • 远程服务的接口定义
  • 远程服务的实现
  • 一台维持远程服务的服务器
  • 一个RMI命名服务,使得客户端能够找到该远程服务。
  • 一个类文件提供商(一个HTTPFTP服务器)
  • 一个需要远程服务的客户端程序
<!--[if !supportLists]-->

在下一节中,通过手把手的方式,你将构建一个简单的RMI系统。建议你在电脑上新建一个文件夹,当你读到对应的步骤时,建立那些文件。

为了简单起见,对客户端代码和服务器代码使用一个目录。从同一个目录中运行客户端和服务器端,你不需要启动一个HTTPFTP服务器来提供类文件。(至于,具体如何使用HTTPFTP服务器作为类文件提供商,这个问题将在“分布和安装RMI软件”一节中具体阐述。)

假设RMI系统已经有了设计,通过以下步骤,你就可以实现这个系统。

  1. 编写并编译接口的Java代码。
  2. 编写并编译实现类的Java代码
  3. 使用实现类来生成桩和框架类
  4. 编写提供远程服务的服务器程序
  5. 开发RMI客户端程序
  6. 安装和运行RMI系统
<!--[if !supportLists]-->

<!--[if !supportLists]-->1. <!--[endif]-->接口

第一步是编写并编译服务的接口的Java代码。Calculator接口定义了所能提供的全部服务。

请注意,该接口继承自Remote ,每个方法签名都声明会抛出RemoteException对象。

拷贝该文件到你的文件夹中,并编译它:

javac Calculator.java

实现

下一步,你要编写远程服务的实现。这是CalculatorImpl类:

再一次拷贝到这些代码到你的文件夹中,并编译它。

实现类使用UnicastRemoteObject 来连接RMI系统。在例子中,实现直接继承自UnicastRemoteObject这并非必须。如果一个类不继承自UnicastRemoteObject,可能使用它的exportObject() 方法来连接RMI系统。

当一个类继承UnicastRemoteObject,它必须提供一个构造器,该构造器声明可能抛出RemoteException对象。当这个构造器调用super()方法时,它执行了UnicastRemoteObject中的某些代码,这些代码执行连接RMI和初始化远程对象的任务。

<!--[if !supportLists]-->2. <!--[endif]-->桩和框架

下一步是,使用RMI编译器——rmic,来生成桩和框架文件。该编译器使用远程服务实现类文件来执行。

>rmic CalculatorImpl

在你的目录下执行该命令。在你执行完rmic命令后,你将会发现Calculator_Stub.class文件,如果你在Java 2 SDK环境下,还有Calulator_Skel.class文件。

JDK1.1RMI编译器rmic,可选项如下:

命令格式:rmic <options> <class names>

<options>包括:

-keep 不删除中间生成文件

-keepgenerated (”-keep”相同)

-g 生成调试信息

-depend 递归的重编译过期文件

-verbose 输出关于编译器正在做什么的信息

-classpath <path> 指定寻找输入源文件和类文件

-d <directory> 指定生成文件存放路径

-J <runtime flag> java解释器传递参数

Java 2平台的rmic增加了三项新参数

-v1.1 创建JDK1.1桩协议版本的桩和框架

-vcompat (默认) 创建兼容JDK1.1Java 2的桩协议版本的桩和框架

-v1.2 只创建Java 2桩协议版本的桩

<!--[if !supportLists]-->3. <!--[endif]-->主机

远程RMI服务必须驻留在一个服务器进程中。类CalculatorServer是一个非常简单的服务器,它提供了最基本的要素。

<!--[if !supportLists]-->4. <!--[endif]-->客户端

客户端源代码如下:

<!--[if !supportLists]-->5. <!--[endif]-->运行RMI系统

现在,请准备运行该系统!需要启动三个控制台,一个给服务器,一个给客户端,一个给RMI注册器。

启动注册器,你必须切换到包含刚才你写的类文件的目录下。然后,输入如下命令:

rmiregistry

如果一切正常,注册器将会开始运行,你可以转换到下一个控制台。

在第二个控制台中,启动服务器,执行CalculatorService, 输入如下命令:

>java CalculatorServer

在最后一个控制台中,启动客户端程序

>java CalculatorClient

如果一切正常,你将会看到以下输出:

1

9

18

3

确是如此;你已经创建一个可运行的RMI系统。尽管你在同一台计算机上运行了三个控制台,在三个独立的JVM中,RMI仍然使用网络栈和TCP/IP来通信。这是一个全面的RMI系统。

分享到:
评论

相关推荐

    rmi基础教程

    rmi基础教程 系统运行机理

    RMI基础代码小程序

    基础代码

    rmi基础知识学习

    rmi不可多得的学习材料!

    RMI 零基础入门与实例

    没有使用过RMI的学者可以参考本资源的实例,比较适用于没有RMI基础的学者,使用分布式编程

    rmi学习笔记(1)

    rmi基础知识学习笔记,从最简单的例子讲述rmi的用途

    关于RMI方面的规范知识

    RMI的基础规范,关于RMI方面的规范知识

    RMI+EHCACHE Demo

    RMI+EHCACHE可以做基础学习理解

    java_in_rmi.rar_Java RMI_RMI java_rmi _精通rmi

    精通RMI 这是RMI的入门基础 特别对刚开始学RMI的同胞们很有帮助

    rmi技术客户端调用服务器的函数解决问题

    在基础知识基本搞定的基础上,我开始了配置环境,经过两天的奋斗,rmi环境配置终于以失败告终,然后一脸遗憾的去问同学,得到的回答是rmi要配置环境?我一脸懵逼,不要配置环境,jar又放不进去,eclipse又不是神仙,...

    Java分布式RMI获取服务器时间

    Java语言编写的简单的分布式Demo,使用RMI远程调用实现,RMI是JavaEE中EJB调用的基础,入门的需要先搞清楚

    JavaBean和RMI 学习

    JavaBean保留了其他软件组件的技术精华,并增加了被其他软件组件技术忽略的技术特性,使得它成为完整的软件组件解决方案的基础,并在可移植的Java平台上方便地用于网络世界中 Java RMI(Remote Method Invocation)-...

    spring rmi 改造

    基于spring rmi的一些小改造,在原基础上加入了线程池控制线程数。

    RMI.zip_HTTP RMI_http视频_rmi视频教程

    用RMI实现的远程视频控制程序,建立在http协议的基础上

    长沙蓝杰实训java课件之 RMI技术解析(www.NetJava.cn)

    做为java分布式计算的基础框架的RMI体系,是javaEE结构的基础技术. 本课件全面讲解了RMI的一般实现,特殊问题解决及与sping的组合应用. 1.分布式计算的起因及基本原理 2.RMI体系结构 3.RMI服务器实现及编码 4.RMI...

    java程序设计与开发课件

    第2章 Java语言基础······························ (11) 2.1 Java语言要素······························ (11) 2.1.1 标识符···········...

    基于RMI的分布式消息传送模型

    本文本的RMI分布式消息传送模型是以一个商业的消息传送平台为基础,将其分布组件结构、点对点和发布/订阅模型、消息队列的实现描绘出来。这个商业消息传送平台暂且称为RMI平台。 主要是一个RMI实现模型,对RMI技术...

    RMI分布式消息传送模型.doc

    本文本的RMI分布式消息传送模型是以一个商业的消息传送平台为基础,将其分布组件结构、点对点和发布/订阅模型、消息队列的实现描绘出来。这个商业消息传送平台暂且称为RMI平台。

    rmi分布式管理初步

    java实现分布式管理的例子程序,从如何使用开始讲起,到最终运行,分布式管理程序的基础

    论文研究-基于JavaRMI的分布式WebGIS模型研究.pdf

    WebGIS是当前GIS的技术热点,立足于WebGIS的分布式特性,在分析Java RMI特点以及优势的基础上,提出基于Java RMI的分布式WebGIS构造模型,并且详细介绍了空间数据模型、组件注册服务器等相关概念和主要实现技术。

Global site tag (gtag.js) - Google Analytics