- 客戶端C通過RMI連接到服務器S
- Ç要求■要創建一個處理程序H,S返回^ h到C
- Ç然後談判與H
現在我可以以兩種方式做到這一點:
- 中號AKE處理程序一
Remote
和令S存根返回到它,所以C進行直接通話的是(h.say(String msg);
) - 給處理程序的ID,並返回到。C將通過S(
s.sayToHandler(int id, String msg);
) 交談至H
首先是更好的面向對象,但性能呢?將打開一個額外的TCP連接,還是使用S和H之間的現有連接?
現在我可以以兩種方式做到這一點:
Remote
和令S存根返回到它,所以C進行直接通話的是(h.say(String msg);
)s.sayToHandler(int id, String msg);
)首先是更好的面向對象,但性能呢?將打開一個額外的TCP連接,還是使用S和H之間的現有連接?
我不知道實施。我不認爲建立了新的連接。但是我知道的是,遠程共享的對象越多,取決於遠程取消引用的對象越多,以便收集垃圾(所以會有更多的對象活得更長,而不是更好)。
替代做法
我給你推薦一個混合的方法。用最好的方式爲客戶端,但在內部實現它的不那麼好的路:
interface Server {
public Handler getHandler(...);
}
interface Handler extends Serializable {
// it gets copied!
public X doThis(...);
public Y doThat(...);
}
class HandlerImpl implements Handler {
public X doThis(...) {
backDoor.doThis(this, ...);
}
public Y doThat(...) {
backDoor.doThat(this, ...);
}
private BackDoor backDoor;
}
interface BackDoor {
public X doThis(Handler h, ...);
public Y doThat(Handler h, ...);
}
class ServerImpl imlpements Server, BackDoor {
public Handler getHandler(...) {
return /*a handler with a self reference as backdoor, only ONE remote obj shared via TWO interfaces */
}
...
// it does everything
// it receives the handler
}
BackDoor的和Handler被sync'ed接口。第一種方法以Handler爲參數,後者具有純方法。我認爲這不是什麼大不了的事。而且這兩個不同的界面讓你在沒有客戶端的情況下乾淨地工作,並允許稀疏的可序列化的Handler執行骯髒的工作。
希望你喜歡它!
RMI規範並沒有真正地說出應該有新的連接還是現有的連接重用。有線協議允許使用或者使用multiplexing或每次調用一個TCP連接(這可能會被重複用於以後調用同一個服務器對象,我不確定)。如果您需要通過HTTP進行隧道傳輸,則每個連接只允許一條消息。
我沒有找到關於如何配置使用哪種類型的協議(禁用HTTP隧道除外)的任何信息。
如果要確保只使用一個TCP連接,請使用自定義客戶端和服務器套接字工廠自行完成多個連接的隧道傳輸。這可能會比RMI運行時系統在那裏的效率低。
我使用這種方法來獲取GWT客戶端(谷歌網絡工具包,所以它的JavaScript)「門票」獲取分頁數據。主要的查詢方法(getCustomers)返回一個票據,客戶可以向票證詢問部分數據(從X到Y檢索)。內在的票:'pageddataservice.retrieve(this,X,Y)'。 pageddataservice(一個衆所周知的服務)查找票證的原始數據提供者(中央註冊表)並執行provider.retrieve(ticket,X,Y)。看起來很複雜,但對於客戶來說是接近神奇的。 – helios 2010-09-15 14:39:44
如果你不介意你可以融合服務器和後門,讓用戶調用'myServer.doThis(handler,...)'或調用更好的'handler.doThis(...)'。它以發佈處理程序接收方法爲代價簡化了一些實現。 – helios 2010-09-15 15:51:12