2011-04-13 68 views
2

我有一個第三方Java庫,我想用RMI封裝在一個單獨的JVM中(因爲這個庫有本地調用導致JVM崩潰,並且有另一臺機器上運行RMI服務器的應用程序)。java RMI:如何檢測服務器是否崩潰?

在客戶端

我的Java應用程序是這樣的,至少當一切都在同一臺機器上運行:

  1. 發現在RMI註冊表
  2. 勢必FooBar/<id>的對象,如果它已經綁定到註冊表,使用它並轉到第5步。
  3. 否則,啓動一個單獨的JVM以創建有問題的對象。
  4. 等待短超時
  5. 發現在RMI註冊表
  6. 勢必FooBar/<id>如果我們有一個目標對象,成功了! (否則失敗)

我遇到的問題是當其他JVM崩潰時,它似乎將綁定存在於RMI註冊表中,然後我最終將虛擬對象連接到任何東西。

有沒有辦法我可以在第2步檢查綁定到RMI註冊表的代理對象,所以如果對象無效,我可以創建一個新的rebind()到RMI註冊表?

回答

3

在您的rmi請求中設置超時(請參閱here)。那麼如果請求超時,則認爲該對象已死亡。此外,當我想要非常可靠的rmi代碼時,我會在客戶端使用某種重試/退避功能(假設您的傳出調用是冪等的)來包裝rmi調用。因此,在考慮目標對象死亡之前,你可以嘗試連接幾次,延遲兩次。

(並且沒有,沒有辦法確定遠程對象是否已經死了,但沒有嘗試聯繫它)。

+0

「沒有辦法確定遠程對象是否已經死亡,但沒有嘗試聯繫它」 - 意思是調用其方法之一?換句話說,至少有一個良性的方法可以打電話。 – 2011-04-13 20:37:48

+2

這並不能真正解決問題。有一個「良性」方法的問題是你可以做出這樣的調用,得到一個響應(然後服務器崩潰),然後嘗試進行真正的調用並獲得超時。最好的解決方案是讓所有的通話都可以重試,只需要進行正常的通話。 (即使正常的呼叫失敗,它可能在服務器上「成功」,但在嘗試返回響應時失敗:最終,你永遠不知道)。 – jtahlborn 2011-04-13 20:51:39

+0

你可以實現一個簡單的'Ping'方法,但這需要主動輪詢,如果你不頻繁地進行RMI調用,這可能會帶來不必要的開銷。即使使用「Ping」調用,在您給Ping打電話之後,仍然無法保證您的對象仍然有效,因此它不是問題的關鍵。您最好管理RMI調用,以便在發生錯誤時可以重新調用它們。 – 2011-04-13 20:56:28