您好,登錄后才能下訂單哦!
RPC(Remote Procedure Call)--遠程過程調用,它是一種通過網絡從遠程計算機程序上請求服務,而不需要了解底層網絡技術的協議。RPC協議假定某些傳輸協議的存在,如;TCP或者UDP,為通信程序之間攜帶信息數據,在OSI網絡通信模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分布式程序在內的應用程序更加容易。
第一層:物理層。這一層主要就是傳輸這些二進制數據。
第二層:鏈路層。將上面的網絡層的數據包封裝成數據幀,便于物理層傳輸;
第三層:網絡層。定義網絡設備間如何傳輸數據;
第四層:傳輸層。管理著網絡中的端到端的數據傳輸;
第五層:會話層。管理用戶的會話,控制用戶間邏輯連接的建立和中斷;
第六層:表示層。定義不同的系統中數據的傳輸格式,編碼和解碼規范等;
第七層:應用層。定義了用于在網絡中進行通信和傳輸數據的接口;
RPC 采用客戶機/服務器模式:請求程序就是一個客戶機,而服務提供程序就是一個服務器。首先,客戶機調用進程發送一個有進程參數的調用信息到服務進程,然后等待應答信息。在 服務器端,進程保持睡眠狀態直到調用信息到達為止。當一個調用信息到達,服務器獲得進 程參數,計算結果,發送答復信息,然后等待下一個調用信息,最后,客戶端調用進程接收 答復信息,獲得進程結果,然后調用執行繼續進行。
通俗的說: RPC 是指遠程過程調用,也就是說兩臺服務器 A,B,一個應用部署在 A 服務器, 想要調用 B 服務器提供的函數和方法,由于不在一個內存空間,不能直接調用,需要通過 網絡來表達調用的語義和傳達調用的數據。也可以理解成不同進程之間的服務調用。
實現的具體步驟:
第一(通訊問題):主要是通過在客戶端和服務器之間建立 TCP 連接,遠程過程調用的所有交換的數據都在這個連接里傳輸。連接可以是按需連接,調用結束后就斷掉,也可以是長連接,多個遠程過程調用共享同一個連接。
第二(尋址問題):A 服務器上的應用怎么告訴底層的 RPC 框架,如何連接到 B 服務器(如主機或 IP 地址)以及特定的端口,方法的名稱以及名稱是什么,這樣才能完成調用。
第三(方法參數的網絡傳遞):當 A 服務器上的應用發起遠程過程調用時,方法的參數需要通過底層的網絡協議如 TCP 傳遞到 B 服務器,由于網絡協議是基于二進制的,內存中的參數的值要序列化成二進制 的形式,也就是序列化(Serialize)或編組(marshal),通過尋址和傳輸將序列化的二進制 發送給 B 服務器。
第四(反序列化):B 服務器收到請求后,需要對參數進行反序列化(序列化的逆操作),恢復為內存中 的表達方式,然后找到對應的方法(尋址的一部分)進行本地調用,然后得到返回值。
第五(返回值):返回值還要發送回服務器 A 上的應用,也要經過序列化的方式發送,服務器 A 接到 后,再反序列化,恢復為內存中的表達方式,交給 A 服務器上的應用
- 讓調用方感覺就像調用本地函數一樣調用遠端函數、讓服務提供方感覺就像實現一個本地函數一樣來實現服務,并且屏蔽編程語言的差異性。
- 讓構建分布式計算(應用)更容易,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性
- 在客戶端 A 上來說,會生成一個服務器 B 的代理。(總結)
RMI(遠程方法調用):JAVA 自帶的遠程方法調用工具,不過有一定的局限性,畢竟是 JAVA 語言最開始時的設計, 后來很多框架的原理都基于 RMI。
Hessian(基于 HTTP 的遠程方法調用):基于 HTTP 協議傳輸,在性能方面還不夠完美,負載均衡和失效轉移依賴于應用的負載均衡 器,Hessian 的使用則與 RMI 類似,區別在于淡化了 Registry 的角色,通過顯示的地址調用, 利用 HessianProxyFactory 根據配置的地址 create 一個代理對象,另外還要引入 Hessian 的 Jar 包。
Dubbo(阿里開源的基于 TCP 的 RPC 框架):基于 Netty 的高性能 RPC 框架。
同其他 RPC 框架一樣,Hadoop RPC 分為四個部分:
- 序列化層:Client 與 Server 端通信傳遞的信息采用了 Hadoop 里提供的序列化類或自定義 的 Writable 類型;
- 函數調用層:Hadoop RPC 通過動態代理以及 Java 反射實現函數調用;
- 網絡傳輸層:Hadoop RPC 采用了基于 TCP/IP 的 socket 機制;
- 服務器端框架層:RPC Server利用Java NIO以及采用了事件驅動的I/O模型,提高RPC Server 的并發處理能力;
Hadoop RPC 在整個 Hadoop 中應用非常廣泛,Client、DataNode、NameNode 之間的通訊全 靠它了。例如:我們平時操作 HDFS 的時候,使用的是 FileSystem 類,它的內部有個 DFSClient 對象,這個對象負責與 NameNode 打交道。在運行時,DFSClient 在本地創建一個 NameNode 的代理,然后就操作這個代理,這個代理就會通過網絡,遠程調用到 NameNode 的方法, 也能返回值。
- 代理:動態代理可以提供對另一個對象的訪問,同時隱藏實際對象的具體事實,代理對 象對客戶隱藏了實際對象。目前 Java 開發包中提供了對動態代理的支持,但現在只支持對 接口的實現。
- 反射:動態加載類
- 序列化:用于將對象進行網絡傳輸
- NIO:非阻塞的異步
- 定義PRC協議:RPC 協議是客戶端和服務器端之間的通信接口,它定義了服務器端對外提供的服務接口。
- 實現PRC協議:Hadoop RPC 協議通常是一個 Java 接口,用戶需要實現該接口。
- 構造和啟動RPC server :直接使用靜態類 Builder 構造一個 RPC Server,并調用函數 start()啟動該 Server。
- 構建RPC client 并發送請求:使用靜態方法 getProxy 構造客戶端代理對象,直接通過代理對象調用遠程端的方法。
1.定義協議
//定義PRC協議
public interface BussinessProtocol {
//在client和server通信的時候,需要版本一致
long versionID=11511056056L;
void mkdir(String name);
void hello(String message);
}
2.實現協議
//實現RPC協議
public class BussinessProtocolImpl implements BussinessProtocol {
@Override
public void mkdir(String name) {
System.out.println("創建了:"+name);
}
@Override
public void hello(String message) {
System.out.println("你好"+message);
}
}
3.構建服務端
//構建RPCserver并啟動服務端
public class MyRPCServer {
public static void main(String[] args) {
RPC.Server server = null;
try {
/**
* 在new RPC.Builder:傳入Configuration對象
* setProtocol(BussinessProtocol.class):設置協議類
* setInstance(new BussinessProtocolImpl()):協議實現類對象
* setBindAddress("localhost"):綁定的主機
* setPort(6789):設置端口
*/
server = new RPC.Builder(new Configuration())
.setProtocol(BussinessProtocol.class)
.setInstance(new BussinessProtocolImpl())
.setBindAddress("localhost")
.setPort(6666)
.build();
} catch (IOException e) {
e.printStackTrace();
}
//啟動服務
server.start();
}
}
4.構建客戶端
//構建 RPC Client 并發出請求
public class MyRPCClient {
public static void main(String[] args) {
try {
/**
* 獲取代理類對象,客戶端通過這個代理可以調用服務端的方法進行邏輯處理:
* Class<T> protocol 協議類的class對象
* long clientVersion:版本
* InetSocketAddress addr:主機端口
* Configuration conf:配置文件對象
*/
BussinessProtocol proxy = RPC.getProxy(BussinessProtocol.class,
BussinessProtocol.versionID,
new InetSocketAddress("localhost", 6666),
new Configuration());
//在客戶端調用了服務端的代理對象的方法
//其實正真的代碼在服務端運行
proxy.hello("zs");
proxy.mkdir("/root/zy");
} catch (IOException e) {
e.printStackTrace();
}
}
}
5.啟動測試
啟動服務端:運行:
啟動客戶端 運行:
觀察服務端console:
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。