2013-12-18 46 views
3

我有一個RMI客戶端測試RMI服務器是否正在運行並且可以到達有沒有一種有效的方法來測試RMI服務器是否啓動?

目前正進行每隔幾秒鐘這個測試:(ping()是一個簡單的啞RMI調用)

try { 
    rMIinstance.ping(); 
} catch (RemoteException e) { 
    getInstanceRegister().removeInstance(rMIinstance); 
} 

如果實例是離線的,我得到約1分鐘後一個

java.net.ConnectException: Connection timed out

異常,表明服務器處於脫機狀態。

但是代碼掛起了一分鐘,這對我們來說已經很長了。 (我不想更改超時設置。) 是否有一種方法可以更快地執行此測試?

回答

2

您可以中斷定時器的線程。這有點怪異,會拋出InterruptedException而不是RemoteException,但它應該工作。

try { 
    Timer timer = new Timer(true); 
    TimerTask interruptTimerTask = new InterruptTimerTask(Thread.currentThread()); 
    timer.schedule(interruptTimerTask, howLongDoYouWantToWait); 
    rMIinstance.ping(); 
    timer.cancel(); 
} catch (RemoteException | InterruptedException e) { 
    getInstanceRegister().removeInstance(rMIinstance); 
} 

而且TimerTask的實現:

private static class InterruptTimerTask extends TimerTask { 
    private Thread thread; 

    public InterruptTimerTask(Thread thread) { 
     this.thread=thread; 
    } 

    @Override 
    public void run() { 
     thread.interrupt(); 
    } 

} 
1

通過@NeplatnyUdaj的回答啓發,我發現這個解決方案:

try { 
    ExecutorService executor = Executors.newSingleThreadExecutor(); 
    Future<String> future = executor.submit(new Task(rMIinstance)); 
    System.out.println("Result: "+ future.get(3, TimeUnit.SECONDS)); 

} catch (RemoteException | TimeoutException e) { 
    getInstanceRegister().removeInstance(rMIinstance); 
} 

而這個任務:

class Task implements Callable<String> { 
     DatabaseAbstract rMIinstance; 
     public Task(DatabaseAbstract rMIinstance) 
     { 
      this.rMIinstance = rMIinstance; 
     } 
     @Override 
     public String call() throws Exception { 
      rMIinstance.ping(); 
      return "OK"; 
     } 
    } 
+1

只是一個小提示:通常你會重用'ExecutorService',因爲它的目的是「緩存」線程。 –

0

的提出的解決方案打斷了線程使得RMI調用可能不起作用,這取決於該線程是否處於可能中斷的地步。普通進行中的RMI呼叫不可中斷。

嘗試將系統屬性java.rmi.server.disableHttp設置爲true。由於RMI故障轉移到其HTTP代理機制,可能會發生長連接超時。該機制在RMISocketFactory的類文檔中進行了描述 - 儘管非常簡短。 (HTTP代理機制在JDK 8中已被棄用)。

+0

我測試了'java.rmi.server.disableHttp' ='true'。它並沒有減少長連接超時。 – user2661619

+0

噢,值得一試。聽起來就像當時發生低層次連接問題。先嚐試ping,然後再嘗試使用RMI,以查看主機是否可訪問並進行響應。 –

0

將系統屬性sun.rmi.transport.proxy.connectTimeout設置爲所需的連接超時(以毫秒爲單位)。我也會設置sun.rmi.transport.tcp.responseTimeout

提示中斷線程的答案依賴於特定於平臺的行爲java.net,其中斷時的行爲未定義。

+0

感謝關於中斷的提示。超時的問題是該虛擬機上的其他RMI實例在超時時應具有一定的容差。 – user2661619

+0

因此,使用適合其他遠程方法的更長的超時時間,並完全擺脫這一點。如果超時到期,其他方法將拋出異常。 – EJP

相關問題