Java RMI的意义是什么?

31

为什么人们使用RMI,或者何时应该使用RMI?我读过Oracle网站上关于RMI的教程,但它没有提供足够的实际示例。

据我所知,软件应尽可能将其模块“无关且分离”。 RMI似乎对我来说是高度耦合的示例。为什么这不是一种糟糕的编码实践?我认为客户端应该只触发指令,而对象的所有实际操作都是由服务器执行的。


任何技术都会遭受某种形式的耦合。你可以选择直接使用套接字,这是一种耦合方式 - 或者HTTP或FTP - 你已经将自己限制在协议的能力范围内。RMI是一种解决方案,旨在允许对象和对象状态的传输,而无需翻译层。如果您只需要与其他Java服务通信,则RMI不是一个坏的解决方案。然而,如果您需要(或您的服务想要)与其他语言通信,则有其他选择可用。这将取决于您的要求。 - MadProgrammer
1
这就是它的设计初衷,但它实际上并没有实现。透明地序列化任意对象图的梦想早已死亡和消失。RMI 实际上推广的是令人尴尬的大量样板文件,称为数据传输对象,其实际上模拟了面向文档的进程间通信,但代价却非常荒谬。 - Marko Topolnik
1
好问题@Will。在你的职业生涯中继续提出这些问题,以识别那些仅因为某个营销人员认为这是个好主意而存在的胡说八道技术。 - Bastian Voigt
1
在我看来,一个问题获得的最佳徽章就是因为它被关闭为“不具建设性” :D - Bastian Voigt
4个回答

31

如果你正在构建应用程序,今天你真的不应该使用RMI,基本上是因为你刚才列出的原因。

在某些情况下(深入遗留或“企业”应用程序),你别无选择。

然而,如果你正在开始一个新项目,其他选项包括:

REST + JSON over HTTP

用于远程服务通信的事实标准。它最大的优点是轻量级且易于理解概念。

理论上,它应该比RMI需要更多的工作,因为你必须手动制定可用的URL、每个URL中接受的动词等。实际上,我认为RMI的样板并没有真正帮助任何人。

坚持使用Java,Jersey是一个出色的库,可以编写自己的RESTful web服务。

如果你想要一个包含电池的解决方案,以便在java中使用RESTful web服务,Yammer公司的Dropwizard提供了一个完整的服务器和框架,只需插入您的业务逻辑,并提供日志记录、数据库连接、序列化、请求路由,甚至度量收集等一切。

SOAP

与远程服务通信的以前标准。除非你有理由使用它,否则我会坚持使用REST。

Thrift

Thrift将创建客户端和服务器存根,从而完成大部分工作。通信采用高效的二进制协议。在Java世界中,它正在变得越来越受欢迎,因为许多开源项目在“大数据”领域中使用它。例如Cassandra、HBase(切换到Avro)。Scrooge是Twitter项目,旨在为Scala创建成语存根。

Akka actors

Akka是一个为Scala和Java实现Actor模型的框架。它提供了服务间通信的支持,并且处理了许多底层细节。


根据您的需求,一些框架可能比其他框架更适合。


更新了我的答案,表明有时确实无法避免 :) - Alex Recarey
如果我想要构建一个客户端-服务器应用程序,其中客户端和服务器都是用Java编写的。我是否还应该使用REST、JSON? - FuryFart
1
即使您的客户端和服务器都是用Java编写的,我仍然会坚持使用HTTP + JSON。如果将来您想要一个Android或iOS应用程序怎么办?如果您需要将服务暴露给另一个未使用Java编写的服务怎么办?即使您永远不需要执行任何这些操作,RMI也很麻烦,其基本前提是有缺陷的,我不会使用它。 - Alex Recarey

9
任何时候,如果您的函数需要一些大型集中计算能力或昂贵的资源(例如巨大的数据库),但您的输出需要被部署到无法承载这种工作负载的许多地方,那么您将考虑远程方法调用。以网络为例,您没有谷歌的副本来计算任何搜索结果,您会在需要结果的瞬间远程调用谷歌服务器。RMI是一种协议/系统,用于在服务器上分发应用程序并分离需要访问该代码结果的客户端。
RMI还可以作为保护应用程序某些方面(如专有算法)的一种方式。 RMI不是唯一的方法,您也可以使用HTTP、SOAP等。许多其他方法提供其他功能,例如真正的语言透明度、更容易和更高效的实现以及更好的解耦。
以下是文档中RMI的声明目标。
支持Java编程语言中分布式对象的目标是:
  • 支持在不同虚拟机上的对象进行无缝远程调用
  • 支持服务器向小应用程序发出回调
  • 将分布式对象模型自然地集成到Java编程语言中,同时保留大部分Java编程语言的对象语义
  • 突显分布式对象模型与本地Java平台的对象模型之间的差异
  • 尽可能简化编写可靠的分布式应用程序
  • 保留Java平台运行时环境提供的类型安全性
  • 支持各种远程对象的引用语义;例如活动(非持久)引用、持久引用和惰性激活
  • 维护由安全管理器和类加载器提供的Java平台的安全环境。所有这些目标的基础是RMI模型既简单易用又自然适合该语言的一般要求。

3
抱歉,你的帖子听起来对RMI过于乐观。我会投反对票以强调其他答案中持怀疑态度的声音。 - Bastian Voigt
2
如果我能和2013年的自己交谈,我会说大部分的话都是一样的 :) - Jason Sperske
哈哈,这让我的一天都美好了 :D - Bastian Voigt

9
你说得对,RMI是服务提供者和服务使用者之间耦合过于紧密的例子。事实上它比表面看起来更糟糕:你永远不知道会有什么异常传递到客户端,导致 ClassNotFoundException掩盖了真正发生的错误。RMI以及类似的EJB都是过去的技术,那个时代相信"透明分布式对象"的幻想。

今天的远程服务基于与RMI完全相反的方法:REST和JSON。


4

RMI的使用场景则与RPC完全相反,它适用于需要紧密绑定的情况,甚至紧密到仿佛是本地方法调用一样。如果您不需要这种紧密绑定,请勿使用它。整个RPC范式并不适用于所有人,包括我在内,即使我写了一本关于RMI的书,但每种工具都有其用途。例如,Java EE就是建立在RMI模型之上的。


2
“Java EE是建立在RMI模型之上”的说法有些值得商榷。我的意思是,Java EE由许多部分组成,其中大部分与RMI无关。即使是EJB最初作为更高级别的RMI抽象构建,现在也很少使用它,以至于Java EE速度领先者已经提议完全删除它。” - Arjan Tijms
@ArjanTijms 链接失效。 - user207421
1
我并不认为Rest和Soap比RMI耦合更少,唯一的区别是RMI在幕后进行耦合,并让编译器检查客户端-服务器接口,而Rest和Soap则需要在应用程序代码中进行耦合和检查。如果Json或XML中未满足客户端-服务器接口,则会破坏您的应用程序,因此您必须在代码或xsd中检查所有内容。 - weberjn
@typelogic,你肯定是指HTTP,而不是HTML,但总的来说,你的评论读起来像是纯粹的20世纪80年代无事实依据的大趋势。 - user207421
@user207421 的回答涉及紧绑定(tight binding),但我认为RMI的绑定与其他明显的替代方案一样紧密。 - weberjn
显示剩余8条评论

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