【问题标题】:Running an RMIRegistry on a different host to RMIServers在与 RMIServer 不同的主机上运行 RMIRegistry
【发布时间】:2010-10-28 01:28:50
【问题描述】:

这可能吗? (假设 Java 6)

一个人为/简单的例子来说明我的观点是:

  • 我有一个定义明确的 RMI 接口,永远不会改变(一个 JAR 文件,没有模板参数)
  • 在主机 X 上运行的 RMIRegistry;
  • RMI 服务,它从主机 Y 到它的 registry.rebind()(主机 X 上的 RMIRegistry);和
  • 从主机 Z 执行 RMI 调用的 RMI 客户端

如果可能,我将如何在 RMI 服务(主机 Y 上的进程)上指定属性“java.rmi.server.codebase”? p>

如果主机 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 在不同的机器上,我通过网络服务器提供接口 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 能够对运行在机器 Y 上的服务进行 RMI 调用。我正在为机器 Y 和 Z 上运行的进程提供 myCommonInterface.jar。我不'甚至不希望机器 X 必须使用通用(远程)接口做任何事情!

虽然以下链接很有用,但它并不能帮助我回答这个问题:http://download.oracle.com/javase/1.4.2/docs/guide/rmi/codebase.html

【问题讨论】:

    标签: java rmi rmiregistry


    【解决方案1】:

    这可能吗?

    不,这是不可能的。请参阅 Registry.bind()/rebind()/unbind() 和 Naming.bind()/rebind()/unbind() 的 Javadoc。

    但是,您可以使用 LDAP 服务而不是 RMI 注册表。

    我只希望机器 Z 能够 对正在运行的服务进行 RMI 调用 在机器 Y 上

    那么为什么要问这个问题?机器 Z 在机器 Y 上查找注册表有什么问题?

    【讨论】:

    • 基本上我希望所有系统都在一台“IT 控制”机器上运行(2 个 RMI 客户端、RMI 注册表、2 个 RMI 服务中的 1 个)。由于各种限制,将只有一个 RMI 服务在单独的“非 IT 控制”机器上运行。 ......这很遗憾 - 这似乎是 RMI 的一个相当大的缺陷 - 它允许各种远程处理可用,但将注册表限制为“不是远程的”,可以这么说!现在感谢您提供的信息 - 至少我会放弃用这个把头撞到墙上!
    【解决方案2】:

    不完全是一个具体的答案,但暗示了限制:

    http://download.oracle.com/javase/6/docs/api/java/rmi/registry/Registry.html

    注册表实现可以选择限制对其部分或全部方法的访问(例如,改变注册表绑定的方法可能仅限于来自本地主机的调用)。如果 Registry 方法选择拒绝对给定调用的访问,它的实现可能会抛出 AccessException,它(因为它扩展 RemoteException)在被远程客户端捕获时将被包装在 ServerException 中。

    【讨论】:

      【解决方案3】:

      我的用例非常简单(基本上,使用 RMI 作为命令分布式系统的一种方式),但我能够避免一起使用注册表。

      这是我最终用于 Map-Reduce-miniframework 的解决方法。

      之前:

      In client:    
          remoteMaster = (Master) remoteRegistry.lookup("master");
          // Add self to remote registry (BAD!)
          Worker stub = (Worker) UnicastRemoteObject.exportObject(this, 15213);
          remoteMaster.bind("workerName", stub);
      

      之后:

      (在此解决方法中,我们将手动保存 RemoteObject,而不是使用注册表)

      In Master:
           List<Worker> workers = new List<Worker>();
      
           public void registerWorker(String name, Worker stub) throws RemoteException {
                worker.add(stub);
            }
      

      一旦你保存了远程实例,你可以传递它并像任何其他对象一样调用它。

      请注意,此方法仅在您仅将注册表用作临时存储位置(我曾经使用过)时才有用,因为您只是通过不将其添加到注册表并保留它来避免“访问限制”当地的。

      只是记录我的(有点 hacky)解决方案,欢迎 cmets。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-10
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多