RMI 双向通信,无需 2 个 RMI 服务器

发布于 2024-11-29 19:59:24 字数 1663 浏览 0 评论 0原文

我之前曾在许多项目中成功使用过 RMI(在 Java 6 中),其中存在明确定义的客户端/服务器关系。当我在以前的项目中使用它时,我创建了一个定义良好的接口 JAR,将其部署到客户端和服务器,并使用“-Djava.rmi.server.codebase=... -Djava”启动 RMI 服务器.rmi.server.hostname=localhost -Djava.security.policy=...\server.policy"

我现在尝试使用 RMI 执行双向通信,以构建基本集群。具体来说,我希望 B(工作人员“客户端”)向 A(中央“服务器”)注册。但是,我希望 B 实现 java.rmi.Remote 接口并将自己的引用传递回 A。这样做的主要动机是: * A 不需要知道 B 的所有实例驻留在哪里(如果需要,它们可以位于互联网上的任何位置!) * 一旦B的实例向A注册,那么A就可以控制B(即,根据A的判断对B执行任务)。

我的问题是,每当我尝试将此远程接口 (B) 作为参数传递回 A 时,我都会在 B 上收到以下异常(但如果我传递 null,则远程调用将成功发生,这使得这种解释不太可能:< a href="http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html#section6" rel="nofollow">http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html#section6 ):

ERROR com.mycompany.server.dao.ServerInterfaceImpl - RMI registerWorker() failed: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.mycompany.worker.MyWorker (no security manager: RMI class loader disabled)

其中: * A(实现)= com.mycompany.server.dao.ServerInterfaceImpl * B = com.mycompany.worker.MyWorker

(Q1) 是否可以执行我所描述的操作?有人能够编写我所描述的超级基本版本(即客户端 B 向服务器 A 注册,然后将对 B 的远程接口的引用传递给 A,以便 A 可以控制 B)?我最初假设我有一些模糊的拼写错误/配置问题,但我开始认为这个任务是不可能的...

(Q2)如果我想做的事情不可能,另一个想法是将 B 的每个实例变成一个 RMI 服务器,并在 B 连接到 A 后让 A 连接到 B。我不想这样做的主要原因是我希望 A 和 B(的每个实例)将被互联网分开,并且只有 A 拥有公共互联网地址(每个实例B 没有公共 IP 地址,并且可能被困在各种防火墙后面,这样 B 更容易连接到 A,反之亦然)...最终,一旦 B 有连接到A,我只是想方便双向通信!

(Q3)我正在考虑在 A 和 B 之间建立心跳。一种可能性是使用每个 B 的这些心跳来轮询 A 是否有任何未完成的工作...我更喜欢 A 异步控制 B,但是...

I have used RMI (in Java 6) successfully before in a number of projects, where there was a well-defined client/server relationship. When I have been using it in previous projects, I have created a well-defined interface JAR which is deployed to both client and server, and start the RMI Server with the "-Djava.rmi.server.codebase=... -Djava.rmi.server.hostname=localhost -Djava.security.policy=...\server.policy"

I am trying to now use RMI to perform bi-directional communication, in order to build a basic cluster. Specifically, I want B (worker "client") to register with A (central "server"). However, I want B to implement the java.rmi.Remote interface and pass a reference of himself back to A. The main motivations of this are:
* A doesn't need to know where all the instances of B reside (they can be anywhere on the internet, if need be!)
* Once an instance of B has registered with A, then A can control B (ie, perform tasks on B at A's discression).

My issue is that whenever I try to pass this Remote interface (B) as a parameter back to A, I get the following exception on B (but the remote call will occur successfully if I pass null instead, which makes this explanation unlikely: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html#section6 ):

ERROR com.mycompany.server.dao.ServerInterfaceImpl - RMI registerWorker() failed: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: com.mycompany.worker.MyWorker (no security manager: RMI class loader disabled)

Where:
* A (implementation) = com.mycompany.server.dao.ServerInterfaceImpl
* B = com.mycompany.worker.MyWorker

(Q1) Is it possible to do what I am describing? Would someone be able to write a super-basic version of what I am describing (ie, client B registers with server A, and then passes a reference to B's Remote interface to A so that A can control B)? I originally assumed I had some obscure typo/config issue, but I am starting to this this task is not possible...

(Q2) If what I am trying to do is not possible, another idea is to turn each instance of B into an RMI Server, and to get A to connect to B after B has connected to A. The main reason I do not want to do this is that I would expect A and (each instance of) B will separated by the internet, and only A would have a public internet address (each instance of B would not have a public IP address, and could be stuck behind various firewall(s), such that it is easier for B to connect to A than vice-versa) ... at the end of the day, once B has connected to A, I just want to facilitate bi-directional communication!

(Q3) I was considering having heartbeating between A and B. One possibility could be to use these heartbeats for each B to poll A with any outstanding work... I would prefer for A to asynchronously control B, however...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

面如桃花 2024-12-06 19:59:24

java.lang.ClassNotFoundException:com.mycompany.worker.MyWorker

这意味着该类不存在于尝试反序列化它的节点上。所以把它放在那里。

如果防火墙允许,您所尝试的将会起作用。如果涉及互联网,您基本上可以忘记它。

java.lang.ClassNotFoundException: com.mycompany.worker.MyWorker

That means that that class isn't present at the node which tried to deserialize it. So put it there.

What you are attempting will work, firewalls permitting. If the Internet is involved you can basically forget it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文