【问题标题】:Java RMI Server in Docker ContainerDocker 容器中的 Java RMI 服务器
【发布时间】:2017-10-01 06:44:00
【问题描述】:

在服务器中,我正在运行带有 RMI 服务器 jar 文件的 docker 容器。 我尝试了几种不同的配置,但我无法让它工作。 我的服务器端:

public class Main extends UnicastRemoteObject implements RmiServerIntf {


public static final String MESSAGE = "Hello World from docker in RMI";

public Main() throws RemoteException {
    super(0);    // required to avoid the 'rmic' step, see below
}

public String getMessage() {
    return MESSAGE;
}

public static void main(String args[]) throws Exception {
        System.out.println("RMI server started");
        System.setProperty("java.rmi.server.hostname", "<host-ip-address>");

        try { //special exception handler for registry creation
            LocateRegistry.createRegistry(1099);
            System.out.println("java RMI registry created.");
        } catch (RemoteException e) {
            LocateRegistry.getRegistry();
            System.out.println("java RMI registry already exists.");
        }

        //Instantiate RmiServer

        Main obj = new Main();

        // Bind this object instance to the name "RmiServer"
        Naming.rebind("RmiServer", obj);
        System.out.println("PeerServer bound in registry");
}

}

我的客户:

public class Main {


public Main() {
}

public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException {
    RmiServerIntf obj = (RmiServerIntf) Naming.lookup("rmi://<my-host-address>:4023/RmiServer");
    System.out.println(obj.getMessage());
}

}

他们都共享“RmiServerIntf”

我的 Dockerfile:

FROM ubuntu:latest
RUN echo "Updating ubuntu image"
RUN apt-get update && apt-get install -y \
    openjdk-8-jre
EXPOSE 1099
COPY RMIServer.jar /home/RMIServer.jar
CMD ["java", "-jar", "/home/RMIServer.jar"]

我开始我的容器:

docker run --name rmitest -d -p 4023:1099 rmitestimage

客户把我扔了:

Exception in thread "main" java.rmi.ConnectException: Connection refused to host: <my-host-address>; nested exception is: 
java.net.ConnectException: Connection refused (Connection refused)
at sun.rmi.transport.tcp.TCPEndpoint.newSocket(TCPEndpoint.java:619)
at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:216)
at sun.rmi.transport.tcp.TCPChannel.newConnection(TCPChannel.java:202)
at sun.rmi.server.UnicastRef.invoke(UnicastRef.java:130)
at java.rmi.server.RemoteObjectInvocationHandler.invokeRemoteMethod(RemoteObjectInvocationHandler.java:227)
at java.rmi.server.RemoteObjectInvocationHandler.invoke(RemoteObjectInvocationHandler.java:179)
at com.sun.proxy.$Proxy0.getMessage(Unknown Source)
at com.company.Main.main(Main.java:19)

【问题讨论】:

  • 成功执行LocateRegistry.getRegistry(); 并不能证明注册表存在,因为它不执行任何网络操作。如果您调用LocateRegistry.createRegistry(),您必须将结果存储到静态变量中。

标签: java docker rmi dockerfile


【解决方案1】:

如果您将注册表和远程对象从同一个 JVM 导出到同一个端口,您将克服端口问题。您不需要使用套接字工厂。

static Registry registry;

// ...
registry = LocateRegistry.createRegistry(Registry.REGISTRY_PORT);
// ...
public Main() throws RemoteException
{
    super(Registry.REGISTRY_PORT);
    // ...
}

// ....
Main main = new Main();
registry.rebind("RmiServer", main);

【讨论】:

  • 非常感谢。这个答案昨天本来是金子。我最终用 UnicastRemoteObject.exportObject(obj,port) 做了一些更混乱的解决方案。但是你的看起来更干净。我稍后会试一试。
【解决方案2】:

据我所知,rmi 仅使用 rmiregistry-port 来初始化连接,而实际的数据传输发生在随机端口上。

由于 docker 只允许连接到您已显式链接到主机的端口,因此 RMI 服务器端的初始化正在发生,但来自方法调用的实际数据传输被“阻止”。 这个问题应该可以在自定义 RMI 套接字工厂的帮助下解决。如果我成功,将返回答案。

【讨论】:

  • 这不正确。 RMI 使用注册表来获取存根,它通过连接来获取。然后,存根通过相同或另一个连接与远程对象通信到相同或另一个端口。
猜你喜欢
  • 2016-11-06
  • 2015-07-04
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多