Docker容器中的Java RMI服务器
在服务器中,我运行带有RMI服务器jar文件的docker容器。 我已经尝试了几种不同的配置,但我不能让它工作。 我Serverside集团:Docker容器中的Java RMI服务器
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回声 “更新ubuntu的图像” RUN易于得到更新& &易于得到安装-y \ 的openjdk -8- JRE EXPOSE 1099 COPY RMIServer.jar /home/RMIServer.jar CMD [的 “java”, “罐子”, “/home/RMIServer.jar”]
(对不起,它不会格式化右)
我开始我的容器: 搬运工运行--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);
非常感谢。这个答案昨天就是黄金。我最终用UnicastRemoteObject.exportObject(obj,port)做了一些混乱的解决。但你的看起来很干净。稍后我会试一试。 – OhLongJohnJohnson
它已经开始了在RMI只使用rmiregistry中端口初始化连接我的知识和实际的数据传输是发生在随机端口。
因为docker只允许连接到你明确链接到主机的端口,RMI服务器端的初始化正在发生,但方法调用的实际数据传输是“阻塞的”。 这个问题应该可以通过定制的RMI套接字工厂来克服。如果我成功了,我会回复并回答。
这是不正确的。 RMI使用注册表获取存根,并通过连接完成。存根然后通过同一个或另一个连接与远程对象通信到同一端口或另一个端口。 – EJP
'LocateRegistry.getRegistry();'的成功执行并不能证明注册表存在,因为它不执行任何网络操作。如果你调用'LocateRegistry.createRegistry()',你必须将结果存储到一个静态变量中。 – EJP