`
dannyhz
  • 浏览: 379157 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

深入理解rmi原理

    博客分类:
  • rmi
RMI 
阅读更多
深入理解rmi原理

http://www.jianshu.com/p/2c78554a3f36


来翻译一篇rmi原理性文章:

成文动机

写这篇文章是出于我个人的经验,我是最近才知道java rmi这个东西的。但是立即我对这部分内容产生了浓厚的兴趣,尤其是 stubs 和skeletons。让我特别的感兴趣的是RMI的设计者设计的这个框架使得rmi客户端感觉就好像在调用本地方法一样,但是实际上是在远程对象上执行的。随着我学习的深入,我开始了解了RMIRegistry和更多的东西。对很多的问题我都很困惑,比如RMIRegistry 真正的角色是什么?他是必须存在的么?stub对象是在哪里创建的?(服务端?客户端?注册中心?),客户端怎么知道服务端监听的端口是哪一个?难道所有的服务端都是使用1099来监听客户端的吗?

这篇文章试图来回答我之前的这些疑惑。我参考了网上很多关于rmi书籍和文章,但是都不能找到这些疑惑的线索,没有人告诉我这些事情都是怎么运转的,每个人都在告诉我怎么写代码,如此而已,没有任何关于底层的工作机制。经过很长时间的研究和实验,我得到了我想要的答案。所以我想分享我的知识,因为还有很多人可能遇到和我同样的疑惑。

这篇文章试图来回答关于RMI原理的几个问题:
1、谁创建了stubs对象,服务器?客户端?注册中心?
2、怎么知道服务器监听的端口是哪一个?
3、注册中心对于RMI系统来说是必须的吗?
4、如果没有注册中心,RMI可以运行吗?

在下面的部分我会详细解答这些问题,如果你想快速得到这些问题的答案,可以直接去看对应的部分,这里我会一步一步的引导你理解rmi中到底发生了什么

首先,请忘记注册中心 !!

是的,从现在开始忘掉注册中心,假设这玩意从现在开始不存在
最开始的场景大概是这样的:我们有一个server和一个client。server 继承了 java.rmi.server.UnicastRemoteObject。client和server运行在不同的机器上面
现在我们的需求是这样的:client想执行一个在远程机器上server的一个方法。

我们如果做到这一点?java rmi 会处理这些问题,解决方案肯定会涉及到socket网络编程,因为server运行在远程机器上,解决这个问题的关键点在于
1.客户端如何从处理网络连接中解耦开来
2.客户端如何能就像调用本地方法一样来调用远程机器上的方法,因此rmi的开发人员就引入了stub和skeleton模型。

所有与网络相关的代码都放在了stub和skeleton中,这样客户端和服务端就不需要处理网络相关的代码了。stub同样也实现了和服务端同样 java.rmi.Remote接口,这样当client想调用server上方法的时候,就可以调用stub上的相同的方法,但是stub里面只有和网络相关的处理逻辑,并没有对应的业务处理逻辑,比如说server上有一个add方法,stub中同样也有一个add方法,但是stub上的这个add方法并不包含添加的逻辑实现,他仅仅包含如何连接到远程的skeleton、调用方法的详细信息、参数、返回值等等。

所以,目前看来大概是这个样子的:
Client<-->stub<-->[NETWORK]<-->skeleton<-->Server

客户端和stub对话,stub和skeleton对话,skeleton和server对话,server执行真正的方法,然后把结果原路返回,这样看来就有4个独立的部分,也就是说你大概需要4个class了。

在jdk1.2之后,skeleton就被合并到server中了,所以看起来是这个样子滴:
Client<--->stub<--->[NETWORK]<--->Server_with_skeleton

socket 层的详细内容

现在,你可以学习在socket层通信是如何完成了的,这部分非常重要!,这部分内容开始变的有点绕,所以,请特别注意这部分内容。

1.server在远程机器上监听一个端口,这个端口是jvm或者os在运行时随机选择的一个端口。可以说server在远程机器上在这个端口上导出自己。
2.client并不知道server在哪,以及sever监听哪个端口,但是他有stub,stub知道所有这些东西,这样client可以调用stub上他想调用的任何方法。
3.client调用给你stub上的方法
4.stub链接server监听的端口并发送参数,详细过程如下:
a.client连接server监听的端口
b.server收到请求并创建一个socket来处理这个链接
c.server继续监听到来的请求
d.使用双方协定的歇息,传送参数和结果
e.协议可以是JRMP或者 iiop
5.方法在远程server上执行,并发执行结果返回给stub
6.stub返回结果给client,就好像是stub执行了这个方法一样。

所以整个过程就结束了,但是等一下!回头再看第2点,说stub知道server在哪,他监听的端口,这怎么么可能?如果client不知道server的host和port,他怎么能创建一个知道所有这一切的stub对象呢?更何况是在服务端端口是随机选择的

启动的窘境

这是在很多现实生活中最大的问题之一。解决方案在于我们如何通知client这些server端的细节。RMI的设计者们有应对启动问题的应急措施,那就是RMIRegistry 存在的必要了。RMIRegistry 可以认为是一个服务,它提供了一个hashmap,里面是 public_name, Stub_object 名值对。比如我有一个远程服务对象叫做 Scientific_Calculator,然后我想把这个服务对外公布为 calc,这样会在server上创建一个stub对象,燃火把他注册到RMIRegistry ,这样client就可以从RMIRegistry 中得到这个stub对象了,你可以使用一个工具类 java.rmi.Naming 来方便的操作注册和操作。

用一个栗子来说明整个过程

考虑一个计算的应用,它有一个add的方法,你想把这个方法对外发布成一个远程对象,远程接口叫做Calc



Paste_Image.png



Paste_Image.png

这就是所有的类,编译这些类得到class,使用RMI 编译器生成stub的class,使用.keep选项得到源代码。



Paste_Image.png

Source code for CalcImpl_Stub.java:



Paste_Image.png

现在看一个这个生成的stub源代码,注意到他的构造参数需要个RemoteRef类型的对象,这个对象从哪里获取呢?继续下面看。
下面先运行程序:
开2个console



Paste_Image.png

然后就可以看到结果:7!!!
这里到底是怎么搞得?

我会给你看这个背后到底发生了什么
1.首先RMIRegistry 运行在server端,RMIRegistry 自身也是一个远程对象。有一点需要注意的是:所有的远程对象(继承了UnicastRemoteObject对象)都会在sever上任意的端口导出自己,因为RMIRegistry 也是一个远程对象,他也在server上导出自己,只是这个端口是广为人知的1099,“广为人知”的意思是所有的client都知道这个端口

2.服务端运行在server上,在UnicastRemoteObject构造函数里面,他把自己导出在server上一个任意端口上,这个端口client是不知道的

3.当你调用Naming.rebind()的时候,会传入一个CalcImpl 的引用(这里叫做 c)作为第2个参数,Naming 就会构造一个stub对象,详细如下:
a.Naming会使用getClass来获取类的名字,这里就是CalcImpl
b.加上后缀_Stub 变成了 CalcImpl _Stub
c.加载CalcImpl_Stub.class到虚拟机中
d.从c中获取RemoteRef 对象



Paste_Image.png


e.就是这个ref对象中封装了服务端细节,包括服务端的hostname、port
f.获取了RemoteRef 对象之后,就可以构造stub对象了。
g.传递stud对象到RMIRegistry中进行绑定,即(publicname,stub)
f.RMIRegistry 中内部使用一个hashmap来存储(publicname,stub)

4.当客户端使用 Naming.lookup()的时候,会传入public name 作为参数,RMIRegistry 就会返回stub给客户端调用

RMIRegistry 是必须的吗?

No,RMIRegistry 起到的作用只是为了方便client获取到stub对象,如果还有其他的方法让client拿到stub就不需要RMIRegistry 了,因为client一旦拿到了stub就不需要RMIRegistry 了

直接在client new一个stub对象不就可以了?

No,stub构造函数中需要一个RemoteRef 对象,这个对象只能在server端获取。
分享到:
评论

相关推荐

    RMI原理及应用详解

    **RMI原理及应用详解** 远程方法调用(Remote Method Invocation,简称RMI)是Java平台提供的一种分布式计算技术,允许在不同的Java虚拟机(JVM)之间进行对象方法的透明调用。RMI的核心思想是使Java对象能够跨越...

    RMI原理及实现

    **RMI原理及实现** 远程方法调用(Remote Method Invocation,简称RMI)是Java平台上的一个核心特性,它允许Java对象在不同的JVM之间进行交互。RMI为分布式计算提供了一个简单而强大的模型,使得开发者可以像调用...

    RMI原理详解

    本文将深入探讨RMI的工作原理、组件以及如何在实际项目中应用。 ### RMI工作原理 1. **注册与查找**:在RMI系统中,远程对象必须首先注册到一个名为远程对象注册表(Remote Object Registry)的服务,以便其他...

    java_rmi.rar_RMI java_java.rmi

    Java RMI(Remote Method Invocation,远程方法调用)是Java平台提供的一种分布式计算技术,它允许Java对象在不同的网络...通过实践提供的"rmi"代码示例,你可以深入理解RMI的工作原理,并掌握如何在实际项目中使用它。

    rmi的实例rmi的实例rmi的实例

    远程方法调用(Remote Method Invocation, RMI)是Java平台上的一个重要特性,它允许一个Java对象在一台机器上执行另一个网络中的...通过深入理解RMI的工作原理和实践,开发者能够创建更加健壮、可扩展的网络应用程序。

    JAVA RMI简单例子

    这个"JAVA RMI简单例子"旨在帮助我们深入理解RMI的基本原理和实现步骤。 RMI的核心概念包括远程接口、远程对象和RMIC编译器。首先,我们需要定义一个远程接口,该接口声明了可以在远程服务器上执行的方法。这些方法...

    java RMI实现代码

    通过这个“java RMI实现代码”项目,你可以深入理解RMI的使用方式,包括如何创建远程接口、实现远程对象,以及客户端和服务器端的交互过程。实践中,结合代码注释逐步调试,将有助于更好地掌握这一核心技术。

    一个RMI实例

    通过实践这个RMI实例,你可以深入理解RMI的运行机制,包括对象序列化、网络通信、异常处理等方面的知识。同时,它也展示了Java如何实现分布式系统的可能性,这对于开发大型企业级应用至关重要。

    RMI可运行的示例代码

    首先,让我们深入理解RMI的工作原理。RMI系统由两部分组成:客户端和服务器端。客户端通过接口调用远程对象的方法,而这些调用实际上被转换为网络请求,发送到服务器端。服务器端接收到请求后,执行相应的方法,并将...

    RMI-IIOP 基于SUN

    4. 相关资料:可能包含了关于RMI、IIOP和CORBA的基础知识,以及相关的技术文章和研究,帮助深入理解RMI-IIOP的工作原理和最佳实践。 学习和掌握RMI-IIOP技术,不仅可以提升开发者的分布式编程技能,也有助于设计和...

    rmi.rar_Java RMI_RMI java_RMI policy.all_rmi

    通过研究这些资源,你可以深入理解RMI的工作机制,掌握如何创建远程接口、实现远程对象,以及如何使用RMI注册表进行对象查找和调用。同时,学习RMI的安全配置也非常重要,确保你的分布式系统在提供服务的同时能够...

    java_in_rmi.rar_Java RMI_RMI java_rmi _精通rmi

    这个"java_in_rmi.rar"压缩包包含了学习和精通RMI的基础资料,非常适合初学者深入理解这一主题。 首先,RMI的核心概念是远程方法调用,它允许一个Java对象调用位于另一台计算机上的对象的方法。这种机制依赖于Java...

    rmi-lite 1.0

    【rmi-lite 1.0】是一个轻量级的Java Remote Method Invocation (RMI)实现,它...总的来说,rmi-lite是一个实用的学习资源,有助于开发者深入理解Java RMI的工作原理,并能在实际项目中灵活运用轻量级的远程调用方案。

    RMI入门好例子

    RMI(Remote Method Invocation...通过深入理解并掌握RMI,开发者能够创建出高效、可靠的跨网络应用。所以,这个"RMI入门好例子"对于初学者来说是一份非常有价值的参考资料,能够帮助他们快速上手并理解RMI的工作机制。

    spring RMI简单例子

    在这个简单的例子中,我们将深入理解Spring RMI的工作原理以及如何实现一个基本的Spring RMI应用。 首先,让我们了解RMI的基本概念。RMI允许Java对象在不同的JVM之间进行通信,仿佛它们都在同一台机器上。它通过...

    RMI应用实例及实验报告

    在本实验中,我们将深入理解RMI的工作原理,并通过实际操作来掌握其应用。 首先,RMI的核心概念是远程接口(Remote Interface)。远程接口定义了可以在远程对象上执行的方法,这些方法的调用会像本地方法一样透明。...

    java rmi HelloWorld版(源码)

    详细的学习过程可以参考提供的博客链接,其中应该包含了如何编译、运行和测试这个HelloWorld示例的步骤,以及更深入的RMI原理和技术细节。通过这个简单的例子,你可以理解RMI的工作机制,并为更复杂的分布式系统打下...

    java RMI技术实现的网络聊天室

    理解套接字编程的基本原理有助于深入理解RMI的工作机制。 以上是关于“java RMI技术实现的网络聊天室”的主要知识点。通过这个项目,开发者可以学习到如何使用RMI创建分布式应用,以及如何处理并发和网络通信等问题...

    rmi_java项目实例

    通过深入研究这个"rmi_java项目实例",不仅可以掌握RMI的基本用法,还能了解到如何在实际项目中应用分布式计算技术,提升你的Java开发能力。同时,此项目也提供了一个交流和学习的平台,你可以联系项目作者讨论和...

    RMI.rar_gui with rmi in ja_rmi _rmi gui_simple rmi with GUI

    Java Remote Method ...通过分析和理解这个项目的代码,你可以深入理解RMI的工作原理,以及如何在实际应用中使用RMI技术来构建分布式系统。同时,这也是对多线程、网络编程和异常处理等Java核心概念的实践应用。

Global site tag (gtag.js) - Google Analytics