我正在尝试为分布式系统项目实现Raft一致性算法。如何快速检查RMI注册表?
我需要一些非常快速的方法来知道服务器A是否可以从服务器B到达并且A的分布式系统已启动。换句话说,可能发生A可以通过B到达,但是A的云系统还没有到达。所以我认为InetAddress.getByName(ip).isReachable(timeout);
是不够的。
由于每个服务器的存根被重命名为服务器的名称,我以为要获取服务器的注册表,然后检查是否存在与服务器名称相同的存根:如果不是这种情况,则跳到下一个服务器,否则执行lookup
(这可能需要一个looong时间)。这是部分代码:
try {
System.out.println("Getting "+clusterElement.getId()+"'s registry");
Registry registry = LocateRegistry.getRegistry(clusterElement.getAddress());
System.out.println("Checking contains:");
if(!Arrays.asList(registry.list()).contains(clusterElement.getId())) {
System.out.println("Server "+clusterElement.getId()+" not bound (maybe down?)!");
continue;
}
System.out.println("Looking up "+clusterElement.getId()+"'s stub");
ServerInterface stub = (ServerInterface) registry.lookup(clusterElement.getId());
System.out.println("Asking vote to "+clusterElement.getId());
//here methods are called on stub (exploiting costum SocketFactory)
} catch (NoSuchObjectException | java.rmi.ConnectException | java.rmi.ConnectIOException e){
System.err.println("Candidate "+serverRMI.id+" cannot request vote to "+clusterElement.getId()+" because not reachable");
} catch (UnmarshalException e) {
System.err.println("Candidate " + serverRMI.id + " timeout requesting vote to " + clusterElement.getId());
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
System.out.println("Candidate "+serverRMI.id+" NotBound "+clusterElement.getId());
}
现在的问题是服务器粘在行获取,因为打印的信息Checking contains
而Looking up...
不是。
为什么会发生这种情况?有什么办法可以加快这个过程?这种算法是超时的完全,所以任何建议将非常感激!
UPDATE: 正在尽一切VM财产有关RMI的超时,如后: -Dsun.rmi.transport.tcp.responseTimeout=1 -Dsun.rmi.transport.proxy.connectTimeout=1 -Dsun.rmi.transport.tcp.handshakeTimeout=1
我没有看到任何差别,即使异常应已在每一个RMI操作时,抛出(因为每个超时设置为1毫秒!)。
,我发现了这个问题,唯一的解决办法就是用这种RMISocketFactory
重新实现:
final int timeoutMillis = 100;
RMISocketFactory.setSocketFactory(new RMISocketFactory()
{
public Socket createSocket(String host, int port)
throws IOException
{
Socket socket = new Socket();
socket.setSoTimeout(timeoutMillis);
socket.connect(new InetSocketAddress(host, port), timeoutMillis);
return socket;
}
public ServerSocket createServerSocket(int port)
throws IOException
{
return new ServerSocket(port);
}
});
感谢您的回复,但我认为有关RMI属性的java文档完全是一团糟。无论如何,我更新了原始问题,包括我用来超时存根方法调用的SocketFactory。你认为这个超时是否也用于“loookup”操作? – justHelloWorld 2015-03-31 09:16:38
您的套接字工厂只设置读取超时。它还需要设置连接超时,但即使如此,它也不会做任何不能被我所指的系统属性所控制的任何事情。这些文件足以让我理解它。我建议你更努力。 – EJP 2015-03-31 09:20:18
好吧,通过文档我发现这三个intersting属性: 'sun.rmi.transport.proxy.connectTimeout':它似乎是我正在寻找的,因为它是关于创建套接字的超时。我不理解的部分是关于HTTP的部分。 'sun.rmi.transport.tcp.handshakeTimeout':这可能也是,但我不这么认为,因为服务器可以访问,所以TCP握手是可能的。 'sun.rmi.transport.tcp.responseTimeout':绝对不是因为它调节方法调用 – justHelloWorld 2015-03-31 09:34:03