對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的時候,故我根據理解畫了這張圖。書上講到需要用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樣例代碼
文件圖
註:在單機環境下模擬,客戶端服務端在不同的文件夾。
服務端
MyRemote.java
View Code
MyRemoteImpl.java
View Code
啟動RMI Registry註冊表服務,注意,此命令沒有任何響應,就是開啟成功了,不要關閉此彈窗
啟動服務,開啟另一個控制台,運行主程序。此主程序同樣沒有任何輸出。
客戶端
MyRemote同上
MyRemoteClient.java
View Code
啟動客戶端,開啟另一個控制台,啟動客戶端主程序
為什麼遠程介面可直接調用Stub
遠程介面能直接調用stub,那很明顯,stub就是遠程介面的實現類。前面我們提到了,用rmic命令工具生生成stub的方式已經被廢除了。stub可以動態生成。但是使用rmic命令工具還是可以生成_stub的class文件。雖然有相關的警告。
我們可以用反編譯工具,來查看其源碼。我使用的是jd-gui。
即,stub確實就是遠程介面的實現類。注意,只是語法上實現,真正的實現在服務端。stub算是一個代理,讓客戶端可以像操作實現類那樣操作stub,好像實現類就在本地一樣。
※回調函數的簡單理解及應用
※10個你應該了解的PHP開源比特幣項目
TAG:程序員小新人學習 |