我之前在许多项目中成功使用过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而远程调用将成功发生,这使得这个解释不太可能: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,但是..
答案 0 :(得分:0)
java.lang.ClassNotFoundException:com.mycompany.worker.MyWorker
这意味着该类在尝试反序列化的节点上不存在。所以把它放在那里。
您尝试的内容将起作用,防火墙允许。如果涉及互联网,您基本上可以忘记它。