什麼是RPCjava
- RPC(Remote Procedure Call,遠程過程調用)
- 通常用來實現部署在不一樣機器上的系統之間的方法調用,
- 使得程序可以像訪問本地系統資源同樣,經過網絡傳輸去訪問遠端系統資源;(!!!)
- 對於客戶端來講, 傳輸層使用什麼協議,序列化、反序列化都是透明的
瞭解 Java RMI程序員
- RMI 全稱是remote method invocation – 遠程方法調用,
- 一種用於遠程過程調用的應用程序編程接口,是純java 的網絡分佈式應用系統的核心解決方案之一。
- RMI 目前使用Java 遠程消息交換協議JRMP(Java Remote Messageing Protocol) 進行通訊,
- 因爲JRMP 是專爲Java對象制定的,是分佈式應用系統的百分之百純java 解決方案,
- 用Java RMI 開發的應用系統能夠部署在任何支持JRE的平臺上
Java RMI 代碼實踐編程
- 遠程對象必須實現UnicastRemoteObject
- 這樣才能保證客戶端訪問得到遠程對象時,該遠程對象會把自身的一個拷貝以Socket 形式傳輸給客戶端
- 客戶端得到的拷貝稱爲「stub」 ,
- 而服務器端自己已經存在的遠程對象成爲「skeleton」,
- 此時客戶端的stub 是客戶端的一個代理,用於與服務器端進行通訊
- 而skeleton 是服務端的一個代理
- 用於接收客戶端的請求以後調用遠程方法來響應客戶端的請求
Java RMI 源碼分析安全
遠程引用層服務器
一步步解讀源碼網絡
- 發佈遠程對象
- 看到上面的類圖能夠知道,這個地方會發布兩個遠程對象,一個是RegistryImpl、另一個是咱們本身寫的RMI 實現類對象;
LocateRegistry.createRegistry(1099);
- 若是服務端指定的端口是1099 而且系統開啓了安全管理器,那麼就能夠在限定的權限集內繞過系統的安全校驗。
- 這裏純粹是爲了提升效率, 真正的邏輯在this.setup(newUnicastServerRef())這個方法裏面
- 有一個問題爲何斷點進去的時候,會重複接收到多個請求
- 這是TCP協議特性
- TCP爲了保證不發生丟包,就給每一個包一個序號,同時序號也保證了傳送到接收端實體的包的按序接收。
- 而後接收端實體對已成功收到的包發回一個相應的確認(ACK);
- 若是發送端實體在合理的往返時延(RTT)內未收到確認,那麼對應的數據包就被假設爲已丟失將會被進行重傳。
- TCP用一個校驗和函數來檢驗數據是否有錯誤;在發送和接收時都要計算校驗和。
- 這個Target 對象基本上包含了所有的信息,等待TCP 調用。
- 包裝實際對象,並將其曝露在TCP端口上,等待客戶端調用
- 用skeleton、stub、UnicastServerRef 對象、id 和一個boolean 值構造了一個Target 對象
- LiveRef 與TCP 通訊的類
- RegistryImpl extends RemoteServer implements Registry
- Skeleton
- private Hashtable<String, Remote> bindings = new Hashtable(101);
- 這個bindings 綁定服務(註冊中心)
- Naming.rebind("rmi://127.0.0.1/Hello",helloService); //註冊中心 key - value
- RegistryImpl_Stub
- LocateRegistry
- UnicastServerRef
- UnicastRemoteObject
- RemoteRef
- Remote
- TCPTransport
- 調用TCPTransport 的listen()方法,listen()方法建立了一個ServerSocket,而且啓動了一條線程等待客戶端的請求。
- Stub和Skeleton:
- 這兩個的身份是一致的,都是做爲代理的存在。
- 客戶端的稱做Stub,服務端的稱做Skeleton。
- 要作到對程序員屏蔽遠程方法調用的細節,這兩個代理是必不可少的,包括網絡鏈接等細節。
- Registry:顧名思義,能夠認爲Registry是一個「註冊重心」,提供了服務名到服務的映射。
- 若是沒有它,意味着客戶端須要記住每一個服務所在的端口號,這種設計顯然是不優雅的。
- 看源碼要看到什麼程度:「看到你以爲你能說服本身就能夠了」