什么是RPC
RPC:Remote Produre Call-遠(yuǎn)程過程調(diào)用,像調(diào)用本地方法一樣調(diào)用遠(yuǎn)程方法
RPC原理
RPC采用客戶端(服務(wù)調(diào)用方)/服務(wù)端(服務(wù)提供方)模式,各自獨(dú)自運(yùn)行。客戶端需要通過引用需要使用的接口,接口的實(shí)現(xiàn)和運(yùn)行都是在服務(wù)端。RPC主要的依賴的技術(shù)包括序列化、反序列化和數(shù)據(jù)傳輸協(xié)議。

2019-01-14.17.45.32-image.png
一些基礎(chǔ)概念
-
RMI(Remote Method Invoke,遠(yuǎn)程方法調(diào)用)代理模式通過代理對(duì)象將方法傳遞給實(shí)際對(duì)象; -
stub(樁)駐留客戶端,承擔(dān)遠(yuǎn)程對(duì)象實(shí)現(xiàn)者的角色; -
skeleton(骨架)幫助遠(yuǎn)程對(duì)象與stub連接進(jìn)行通信。
RPC時(shí)序圖

2019-01-15.12.45.18-image.png
關(guān)于時(shí)序圖的一些解釋:
- 1.客戶端(client)通過本地調(diào)用的方式調(diào)用服務(wù)
- 2.
client stub接收到調(diào)用方法之后將參數(shù)、方法封裝成能夠網(wǎng)絡(luò)傳輸?shù)南Ⅲw(序列化) - 3.
client stub找到服務(wù)地址,并將消息發(fā)送到服務(wù)端 - 4.
server stub接收消息并解碼(反序列化) - 5.
server stub根據(jù)解碼結(jié)果調(diào)用本地服務(wù) - 6.本地服務(wù)獎(jiǎng)?wù){(diào)用結(jié)果返回給
server stub - 7.
server stub將返回結(jié)果打包成消息(序列化)發(fā)送至調(diào)用方 - 8.
client stub接收消息并解碼(反序列化) - 9.客戶端得到最終結(jié)果
常見RPC框架
常見RPC框架方案有RMI(JDK自帶),Hessian,Dubbo,Hprose,Thrift,HTTP等
RMI
RMI調(diào)用過程

2019-01-15.17.23.19-6401.png
- 1.服務(wù)端向RMI注冊(cè)服務(wù)綁定自己的地址
- 2.客戶端通過RMI注冊(cè)服務(wù)獲取目標(biāo)地址
- 3.客戶端調(diào)用本地stub對(duì)象上的方法,與調(diào)用本地方法一致
- 4.本地stub對(duì)象將調(diào)用信息打包(序列化),通過網(wǎng)絡(luò)發(fā)送給服務(wù)端
- 5.服務(wù)端skeleton對(duì)象接收到網(wǎng)絡(luò)請(qǐng)求,對(duì)調(diào)用信息進(jìn)行解包(反序列化)
- 6.服務(wù)端真正服務(wù)調(diào)用發(fā)起調(diào)用,并將返回結(jié)果打包(序列化)發(fā)送給客戶端
- 7.客戶端解包(反序列化)結(jié)果,獲取服務(wù)調(diào)用結(jié)果
Java RMI基本概念
在RMI調(diào)用中,有以下幾個(gè)核心概念
1.通過接口進(jìn)行遠(yuǎn)程調(diào)用
2.通過客戶端stub對(duì)象和服務(wù)端skeleton對(duì)象幫助遠(yuǎn)程調(diào)用偽裝成本地調(diào)用
3.通過RMI注冊(cè)服務(wù)完成服務(wù)的注冊(cè)與發(fā)現(xiàn)
Java RMI示例
接口
HelloService
// 必須繼承Remote接口
public interface HelloService extends Remote {
String sayHello() throws RemoteException;
}
接口實(shí)現(xiàn)
// 必須繼承UnicastRemoteObject類
public class HelloServiceImpl extends UnicastRemoteObject implements HelloService {
// 必須實(shí)現(xiàn)構(gòu)造方法
public HelloServiceImpl() throws RemoteException {
super();
}
public String sayHello() throws RemoteException {
return "Hello World";
}
}
服務(wù)端(Server)
public class RmiServer {
public static void main(String[] args) throws RemoteException {
// 初始化服務(wù)對(duì)象示例
HelloService helloService = new HelloServiceImpl();
// 創(chuàng)建一個(gè)本地RMI服務(wù),監(jiān)聽1099端口
Registry registry = LocateRegistry.createRegistry(1099);
// 將示例對(duì)象注冊(cè)綁定到服務(wù)商,客戶端可以通過Hello這個(gè)名字查找遠(yuǎn)程對(duì)象
registry.rebind("Hello", helloService);
}
}
客戶端(Client)
public class RmiClient {
public static void main(String[] args) throws RemoteException, NotBoundException {
// 獲取注冊(cè)服務(wù)示例,這里假定獲取的注冊(cè)服務(wù)部署在本機(jī)上,并監(jiān)聽1099端口
Registry registry = LocateRegistry.getRegistry();
// 從注冊(cè)中心查找服務(wù)名為Hello的遠(yuǎn)程對(duì)象
HelloService helloService = (HelloService) registry.lookup("Hello");
// 發(fā)起遠(yuǎn)程調(diào)用
System.out.println(helloService.sayHello());
}
}
Dubbo
Dubbo架構(gòu)

2019-01-15.17.08.47-image.png