Docker容器中的Java RMI服务器



在服务器中,我正在使用RMI-Server 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)

如果将注册表和远程对象从同一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);

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

由于Docker仅允许连接到您已明确链接到主机机器的端口,因此正在发生RMI-Server侧的初始化,但是从方法侵蚀中的实际数据传输"阻止"。在自定义RMI插座工厂的帮助下,应该可以克服此问题。如果我成功,将带有答案。

最新更新