分佈式消息通訊框架RMI原理分析

什麼是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
    • stub
  • LocateRegistry
  • UnicastServerRef
    • 內部引用了LiveRef
  • UnicastRemoteObject
    • 字面意思(單播遠程對象)
  • RemoteRef
  • Remote
  • TCPTransport
    • 調用TCPTransport 的listen()方法,listen()方法建立了一個ServerSocket,而且啓動了一條線程等待客戶端的請求。

  • Stub和Skeleton:
    • 這兩個的身份是一致的,都是做爲代理的存在。
    • 客戶端的稱做Stub,服務端的稱做Skeleton。
    • 要作到對程序員屏蔽遠程方法調用的細節,這兩個代理是必不可少的,包括網絡鏈接等細節。
  • Registry:顧名思義,能夠認爲Registry是一個「註冊重心」,提供了服務名到服務的映射。
    • 若是沒有它,意味着客戶端須要記住每一個服務所在的端口號,這種設計顯然是不優雅的。

  • 看源碼要看到什麼程度:「看到你以爲你能說服本身就能夠了」
相關文章
相關標籤/搜索