在与 RMIServer 不同的主机上运行 RMIRegistry
这可能吗? (假设 Java 6)
一个人为的/简单的例子来说明我的观点是:
- 我有一个定义良好的 RMI 接口,它永远不会改变(单个 JAR 文件,没有模板参数)
- 运行在主机 X 上的 RMIRegistry;
- RMI 服务,它从主机 Y 对其进行registry.rebind()(主机 X 上的 RMIRegistry);以及
- 从主机 Z 执行 RMI 调用的 RMI 客户端
如果可能,我将如何在 RMI 服务(主机 Y 上的进程)上指定属性“java.rmi.server.codebase”?
如果主机 A 和 B 是同一台计算机,则当“java.rmi.server.codebase”为“file:///C:/rmiCodebase/myCommonInterface”时,此配置有效 .jar”
如果主机 A 和 B 位于不同的计算机上,则重新绑定时会出现以下异常(在主机 Y 上设置相同的“java.rmi.server.codebase”)
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException:
: A 和 B 位于不同的机器上,我通过 Web 服务器提供接口 JAR(其中“java.rmi.server.codebase”是“http://Y/rmiCodebase/myCommonInterface”) .jar" OR "http://Z/rmiCodebase/myCommonInterface.jar"),然后我在重新绑定时遇到这个略有不同的错误:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Registry.Registry.rebind disallowed; origin /10.0.190.25 (host Y) is non-local host
我有点困惑 - 如果所有 RMI 似乎非常有限制服务必须在与 RMIRegistry 相同的物理主机上运行(这是我成功工作的唯一事情)
最终,我只希望机器 Z 能够对机器上运行的服务进行 RMI 调用Y. 我向机器 Y 和 Z 上运行的进程提供 myCommonInterface.jar。我什至不希望机器 X 必须对通用(远程)接口执行任何操作!
虽然以下链接很有用,但它并不能帮助我回答这个问题: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html
Is this possible? (Assuming Java 6)
A contrived/simplistic example to illustrate my point is:
- I have a well-defined RMI interface that will never change (a single JAR file, no template parameters)
- an RMIRegistry running on host X;
- RMI Services which registry.rebind() to it (RMIRegistry on host X) from host Y; and
- RMI clients which perform RMI calls from host Z
If it is possible, how would I specify the property "java.rmi.server.codebase" on the RMI Service (process on host Y)?
If host A and B are the same machine, then this configuration works when the "java.rmi.server.codebase" is "file:///C:/rmiCodebase/myCommonInterface.jar"
If host A and B are on separate machines, then I get the following exception on the rebind (with the same "java.rmi.server.codebase" set on host Y):
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException:
If host A and B are on separate machines, and I make the interface JAR available through a web-server (where "java.rmi.server.codebase" is either "http://Y/rmiCodebase/myCommonInterface.jar" OR "http://Z/rmiCodebase/myCommonInterface.jar"), then I get this slightly different error on the rebind:
java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.AccessException: Registry.Registry.rebind disallowed; origin /10.0.190.25 (host Y) is non-local host
I am a little confused - it seems very constraining if all RMI Services must run on the same physical host as the RMIRegistry (which is the only thing I have succeeded in getting working)
At the end of the day, I only want machine Z to be able to make an RMI call to a service running on machine Y. I am providing myCommonInterface.jar to the processes running on both machine Y and Z. I don't even want machine X to have to do anything with the common (remote) interface!
Whilst the following link is useful, it doesn't help me answer this question: http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我的用例非常简单(基本上,使用 RMI 作为命令分布式系统的方式),但我能够避免一起使用注册表。
这是我最终用于 Map-Reduce-miniframework 的解决方法。
之前:
之后:(
在此解决方法中,我们将手动保存 RemoteObject,而不是使用注册表)
保存远程实例后,您可以像任何其他对象一样传递它并调用它。
请注意,仅当您仅将注册表用作临时存储位置(我就是这样)时,此方法才有用,因为您只是通过不将其添加到注册表并将其保留在本地来避免“访问限制”。
只是记录我的(有点hacky)解决方案,欢迎评论。
My use-case was very simple (basically, using RMI as a way to command a distributed system), but I was able to avoid using the registry all together.
Here's a work-around to that I ended up using for a Map-Reduce-miniframework.
Before:
After:
(In this workaround, we will save the RemoteObject manually, not using a registry)
Once you save the remote instance, you can pass it around and call it like any other object.
Note this approach is useful only if you're only using the registry as a temporary storage place (which I was), since you're just avoiding the "access restriction" by not adding it to the registry, and keeping it local.
Just documenting my (slightly hacky) solution, comments welcome.
不,这是不可能的。请参阅Registry.bind()/rebind()/unbind() 和 Naming.bind()/rebind()/unbind() 的 Javadoc。
不过,您可以使用 LDAP 服务来代替 RMI 注册表。
那么为什么会出现这个问题呢?机器 Z 在机器 Y 上查找注册表时出现什么问题?
No it is not possible. See the Javadoc for Registry.bind()/rebind()/unbind() and Naming.bind()/rebind()/unbind().
However you could use an LDAP service instead of the RMI Registry.
So why the question? What's the problem with machine Z looking up a Registry at machine Y?
不完全是具体的答案,但暗示了限制:
http://download.oracle.com/javase/6/docs/api/java/rmi/registry/Registry.html
注册中心实现可以选择限制对其部分或全部方法的访问(例如,改变注册表绑定的方法可能仅限于源自本地主机的调用)。如果注册表方法选择拒绝对给定调用的访问,则其实现可能会抛出 AccessException,该异常(因为它扩展了 RemoteException)在被远程客户端捕获时将被包装在 ServerException 中。
Not exactly a concrete answer, but hints at the restriction:
http://download.oracle.com/javase/6/docs/api/java/rmi/registry/Registry.html
A Registry implementation may choose to restrict access to some or all of its methods (for example, methods that mutate the registry's bindings may be restricted to calls originating from the local host). If a Registry method chooses to deny access for a given invocation, its implementation may throw AccessException, which (because it extends RemoteException) will be wrapped in a ServerException when caught by a remote client.