Как быстро проверить реестр RMI?
Я пытаюсь реализовать согласованный алгоритм Рафта для проекта распределенной системы.
Мне нужен очень быстрый способ узнать, доступен ли сервер A с сервера B, а распределенная система A запущена. Другими словами, может случиться так, что A достижим B, но облачная система A еще не запущена. Так что я думаю, что InetAddress.getByName(ip).isReachable(timeout);
не достаточно
Поскольку заглушка каждого сервера переименовывается в имя сервера, я подумал получить реестр сервера и проверить, существует ли заглушка с тем же именем сервера: если это не так, перейдите к следующему серверу, в противном случае выполните команду lookup
(что может занять много времени). Это часть кода:
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());
}
Теперь проблема в том, что сервер застревает на contains()
строка, так как сообщение Checking contains
печатается в то время как Looking up...
нет.
Почему это происходит? Есть ли способ ускорить процесс? Этот алгоритм полон тайм-аутов, поэтому любое предложение будет очень полезно!
ОБНОВЛЕНИЕ: После попытки каждого возможного свойства 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 );
}
} );
1 ответ
Это застревает в Registry.list().
Это будет время ожидания в конце концов.
Тебе лучше просто позвонить lookup()
без этого предыдущего шага, который не добавляет никакой ценности, и изучения всех вариантов времени ожидания, упомянутых на двух страницах свойств, связанных с домашней страницей RMI.