當前位置:
首頁 > 知識 > 對RMI(Remote Method Invoke)的認識

對RMI(Remote Method Invoke)的認識

前言

對RMI接觸的也比較早,基本上剛學完Java基礎不久就機緣巧合遇到了。當時有嘗試著去了解,但是沒看到比較好的教程,而且對網路編程相關知識不太了解,看了不少文章,也沒弄明白。現在對網路和I/O有了一定了解,理解起來也比較順暢了。以下,是我對RMI的認識。

RMI的相關概念

"In computing, the Java Remote Method Invocation (Java RMI) is a Java API that performs remote method invocation, the object-oriented equivalent of remote procedure calls (RPC), with support for direct transfer of serialized Java classes and distributed garbage-collection." ——維基百科

上述定義指明幾個點

  • RMI是Java用於調用遠程方法的API ——①屬於Java ②指的是一個API,不是協議或者其他什麼東西
  • 相當於面向對象版的RPC —— RPC是遠程過程調用(面向過程)
  • 支持直接傳輸可序列化的Java類 ——①傳輸的類是方法調用需要的參數和返回值,而不是實現類,實現類的方法在伺服器執行。
  • 支持分散式垃圾回收(暫未涉獵)

遠程調用

遠程調用並不是載入遠程的類到本地執行,而是通過傳遞方法參數到伺服器,讓伺服器執行相應的方法並返回結果給客戶端。

網路協議與IO

RMI所指的遠程調用,說的其實是從一個JVM的對象調用另一個JVM環境下對象方法的過程。兩個JVM可以在不同的主機上,也可以在同一台主機上。如果在不同主機上,則方法調用必然需要網路傳輸,網路傳輸則必然與Socket通信以及相關的通信協議掛鉤,RMI用的底層協議是JRMIP。值得一提的是,使用RMI這個API的好處就是,用戶不需要實現底層的網路通信與IO,或者說網路傳輸對用戶來說是透明的。

遠程介面

客戶端和服務端都有的介面,只不過介面的實現類在服務端。

RMI的工作原理

對RMI(Remote Method Invoke)的認識

打開今日頭條,查看更多精彩圖片

值得一提的是,我在學習RMI的時候,故我根據理解畫了這張圖。書上講到需要用rmic指令生成stub和skeleton。但是實際上,Java後面已經廢除了這種方式,skeleton被認為不再需要,但是伺服器仍然有一些東西負責skeleton的行為(誰負責,暫不清楚,尚未了解底層實現)。而stub可以動態生成。所以用這張圖理解RMI還是沒問題的。

RMI遠程服務的實現

相關概念

Remote

java.rmi.server包下的定義的介面,遠程介面必須繼承與RMI的Remote介面,表明其遠程介面的身份。

RMI registry

RMI的註冊表服務,伺服器需要將對應的服務註冊到註冊表上,此操操作將會綁定對應服務的stub(存根)。客戶端會根據伺服器的IP地址找到伺服器,然後在伺服器的註冊表上找對應的存根。

UnicastRemoteObject

遠程介面的實現類必須繼承此類,以用於生成與底層JRMP協議相關的通信對象,以及用於與通信對象連接的stub(存根)。

服務端實現步驟

1. 定義遠程介面

定義一個介面,繼承於Remote介面。注意,定義的方法需要拋出RemoteException。因為網路和I/O是不安全的,必須讓客戶意識到這點,做相應的異常處理準備。

2. 定義遠程介面實現

定義一個類實現上述介面,並繼承UnicastRemoteObject。可在此類,或其他類中的main方法中,註冊服務到註冊表表。

Naming.rebind("serviceName", service);

3. 啟動RMI registry註冊表服務

利用命令行啟動。啟動命令所在的目錄必須能夠訪問到你的類。最好在實現類目錄啟動。

%rmiregistry

4. 開啟遠程服務(註冊服務到註冊表)

執行,帶有註冊操作的類。

客戶端實現步驟

1. 定義遠程介面

與服務端的介面相同,直接拷貝過來即可。

2. 定義訪問遠程介面的類

客戶端需要定義一個類,用於連接到服務端的註冊表,根據服務的相關信息查找並獲取stub(存根)。

Naming.lookup("rmi://ip:port/serviceName");

3. 根據stub訪問遠程介面方法。

RMI樣例代碼

文件圖

對RMI(Remote Method Invoke)的認識

註:在單機環境下模擬,客戶端服務端在不同的文件夾。

服務端

MyRemote.java

對RMI(Remote Method Invoke)的認識

View Code

MyRemoteImpl.java

對RMI(Remote Method Invoke)的認識

View Code

啟動RMI Registry註冊表服務,注意,此命令沒有任何響應,就是開啟成功了,不要關閉此彈窗

對RMI(Remote Method Invoke)的認識

啟動服務,開啟另一個控制台,運行主程序。此主程序同樣沒有任何輸出。

對RMI(Remote Method Invoke)的認識

客戶端

MyRemote同上

MyRemoteClient.java

對RMI(Remote Method Invoke)的認識

View Code

啟動客戶端,開啟另一個控制台,啟動客戶端主程序

對RMI(Remote Method Invoke)的認識

為什麼遠程介面可直接調用Stub

遠程介面能直接調用stub,那很明顯,stub就是遠程介面的實現類。前面我們提到了,用rmic命令工具生生成stub的方式已經被廢除了。stub可以動態生成。但是使用rmic命令工具還是可以生成_stub的class文件。雖然有相關的警告。

對RMI(Remote Method Invoke)的認識

對RMI(Remote Method Invoke)的認識

我們可以用反編譯工具,來查看其源碼。我使用的是jd-gui。

對RMI(Remote Method Invoke)的認識

即,stub確實就是遠程介面的實現類。注意,只是語法上實現,真正的實現在服務端。stub算是一個代理,讓客戶端可以像操作實現類那樣操作stub,好像實現類就在本地一樣。

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 程序員小新人學習 的精彩文章:

回調函數的簡單理解及應用
10個你應該了解的PHP開源比特幣項目

TAG:程序員小新人學習 |