RMI服务器与RMI注册表的区别

3
Oracle的Java RMI FAQ页面上,它说:
尽管Java远程方法调用(Java RMI)服务器理论上可以在任何主机上运行,但通常与注册表运行的主机相同,但端口不同。即使服务器对其主机名或IP地址弄错了(或者具有客户端无法解析的主机名),它仍将使用该错误的主机名导出其所有对象,但每次尝试接收其中一个对象时都会看到异常。
我不理解RMI服务器和RMI注册表之间的区别。我以为它们是同一件事。如果RMI注册表不是某种服务器,那么它怎么能工作呢?

2
要真正理解它们之间的区别,您必须阅读此处的“编写RMI服务器” - http://docs.oracle.com/javase/tutorial/rmi/server.html。您将了解到RMI服务器就像一个前门,让您访问在RMI注册表中注册的对象。 - hagrawal7777
修改了注释。 - hagrawal7777
@hagrawal 客户端不会“传递它想要的远程对象的远程引用”。它传递名称,并接收远程引用(存根)作为回报。它不会接收远程对象。 - user207421
我在下面的答案中已经说得很清楚了。 - hagrawal7777
@lmray registryhosts stubs是指对实际服务器的引用。 - eckes
显示剩余5条评论
3个回答

6

RMI注册表是什么:

RMI注册表是一个服务,远程对象在其中注册,RMI客户端查找已注册的远程对象。如果您希望您的对象可以远程访问(可能有很多原因,例如您不断更新逻辑而无法每次都将其发送到实现中,因此通过RMI允许远程调用),则在RMI注册表中注册它,然后RMI客户端将查找远程对象(使用对象的远程引用),然后可以调用远程对象上的方法。

以下是来自Oracle Javadoc的注册表定义

注册表是一种将名称映射到远程对象的远程对象。服务器使用注册表向其注册远程对象,以便可以查找它们。当对象想要调用远程对象的方法时,它必须首先使用名称查找远程对象。注册表返回对远程对象的引用给调用对象,使用该引用可以调用远程方法。

RMI服务器是什么:

RMI服务器是实际运行JVM和对象(远程对象)的服务器。RMI客户端最终需要这个对象。
就您的问题而言,是的,此服务器(RMI服务器)可以与运行RMI注册表的服务器不同。您可以理解为什么!我可以在同一RMI注册表中从不同的服务器注册对象,并且可以在完全不同的服务器上运行该注册表。请阅读下面的更多解释。
Java RMI客户端如何联系远程Java RMI服务器?为了使Java RMI客户端联系远程Java RMI服务器,客户端必须首先持有对服务器的引用(这就是RMI注册表的作用,为您提供对RMI服务器的引用)。 Naming.lookup方法调用是客户端最初获取对远程服务器引用的最常见机制。
每个远程引用都包含一个服务器主机名和端口号,允许客户端定位为特定远程对象提供服务的VM。一旦Java RMI客户端拥有远程引用,客户端将使用引用中提供的主机名和端口来打开到远程服务器的套接字连接。
请务必阅读同一Oracle常见问题解答中的this
您可以很好地连接RMI注册表,但可能无法获取远程对象,这就是人们报告java.net.UnknownHostException的原因,这意味着RMI注册表能够提供远程对象的引用,但实际上托管远程对象或运行对象所在JVM的RMI服务器未找到或客户端无法连接。
因此,RMI注册表和RMI服务器是两个不同的东西。
一个类比可以是HTTP服务器用于提供对服务器上可用的HTTP资源(超文本文档)的访问。然而,通常超文本文档将位于与HTTP服务器相同的物理框中,但是RMI注册表可以提供对位于不同服务器上(RMI服务器)的远程对象的引用的访问。

那么RMI服务器是什么?主机吗?如果是这样,它如何可以“在”任何主机上运行?它如何神奇地“导出对象”?“向注册表注册其远程对象”呢? - user207421
@hagrawal 说“它是唯一的”并没有以任何方式回答我的问题。一个什么?我重复一遍,它是主机吗?还是主机上的某个东西?如果是这样,是什么? - user207421
RMI服务器并不会自动导出对象(或远程对象),而是JVM运行的地方,也是远程对象所驻留的地方。通过RMI注册表返回的远程引用,RMI客户端可以访问此远程对象。请阅读来自Oracle文档的另一行 - “每个远程引用都包含一个服务器主机名和端口号,允许客户端定位为特定远程对象提供服务的VM”。 - hagrawal7777
1
@Imray:那么,你知道RMI服务器和RMI注册表之间的区别了吗? - hagrawal7777
1
@hagrawal 是的,我也这么认为。感谢您启发性的回答和讨论。 - CodyBugstein
显示剩余6条评论

1
一个RMI服务器是托管远程对象的程序。RMI注册表是将远程对象名称绑定到实例的单独程序。通过在注册表中注册远程对象,RMI服务器使客户端可以访问远程对象;然后客户端通过同一注册表获得访问权限。RMI注册表是小写字母“s”的“服务器”,但通常不是“RMI服务器”。RMI服务器和RMI注册表之间的关系类似于Web服务器和其授权DNS服务器之间的关系。也许甲骨文的getting started guide比FAQ更好地解释了这一点。

感谢这个类比。然而,文章中提到:“尽管Java远程方法调用(Java RMI)服务器理论上可以在任何主机上运行,但通常与注册表运行的主机相同。”这有什么道理呢?这就像每个Web服务器都在运行DNS的同一主机上一样。 - CodyBugstein
@Imray,正如文章所说,RMI注册表可以在任何主机上运行。它不必与RMI服务器运行的主机相同,并且只要没有名称冲突,一个RMI注册表可以支持同一主机或不同主机上的多个RMI服务器。通常情况下,RMI服务器使用与其共存于同一主机上的RMI注册表是一种方便的做法。无论如何,“RMI服务器”和“RMI注册表”都指的是程序,而不是它们运行的主机。 - John Bollinger
每个RMI服务器上都有一个RMI注册表的意义是什么?这样一来,客户端需要知道所有这些注册表,而不仅仅是一个。这就像你的家用电脑要通过DNS服务器列表查找网站一样,不是吗? - CodyBugstein
你对我的比喻过于深究了。RMI注册表被设计为能够支持从互联网上的任何地方为客户端提供服务。然而,通常情况下,给定的RMI注册表用于支持已知客户端池对已知服务器池的访问。实际上,给定远程对象所注册的注册表在非常实用的方式上作为注册名称的命名空间。如果你想要一个特定的远程对象,那么你需要知道要询问哪个注册表。 - John Bollinger
在查询注册表之前,您不需要知道的是 RMI 服务器位于哪里。 - John Bollinger

0

来自RMI规范#2.4.3:

RMI服务器功能由java.rmi.server.RemoteObject及其子类java.rmi.server.RemoteServerjava.rmi.server.UnicastRemoteObjectjava.rmi.activation.Activatable提供。

我认为术语混乱且不必要。所有这些意味着每个远程对象都是一个服务器。最好只考虑远程对象。术语“RMI服务器”在RMI规范中仅出现两次,并且两次都明确指的是远程对象。

注册表也是一个远程对象。您可以通过远程方法的返回值获取远程对象。注册表解决了如何启动的引导问题。

相比之下,您引用的Oracle FAQ似乎将“RMI服务器”一词用作“托管”远程对象的一种程序类型:但是根本没有必要存在这样的程序。许多甚至大多数远程对象只是“托管”自己。将这样的程序描述为服务器只是术语的误用。

如果RMI注册表不是某种服务器,它怎么能工作呢?
它是一个远程对象。

Oracle的文档非常清晰,他们的意思是您可以启动RMI服务器,该服务器可能与RMI注册表位于同一主机上,也可能不在同一主机上。他们明确谈到了两件不同的事情。OP链接中的第一行“异常跟踪中看到的主机名和端口号表示被查找的服务器认为自己正在侦听的地址”,这里“被查找的服务器”指的就是RMI服务器。 - hagrawal7777
“RMI 服务器”肯定不会出现在 RMI 规范中,就像“HTTP 服务器”或“Web 服务器”不会出现在 HTTP 规范中一样。我认为 OP 关于 RMI 服务器和 RMI 注册表的疑虑是正确的,但你的回答暗示它们是相同的。 - hagrawal7777
@hagrawal 请不要忘记,OP引用的Oracle文档仅仅是一个常见问题解答,因此在规范等级方面远远低于RMI规范。这篇文档甚至无法明确 'RMI服务器' 是主机还是程序。我的答案是,术语 'RMI服务器' 毫无意义,最好避免使用,而不是将其视为其他任何东西的同义词。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接