我正在嘗試爲分佈式系統項目實現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