定義:RPC(Remote Procedure Call Protocol)——遠程過程調用協議 ,RPC協議假定某些傳輸協議的存在,如TCP或UDP,爲通信程序之間攜帶信息數據。在OSI網絡通信模型中,RPC跨越了傳輸層和應用層 ,RPC使得開發包括網絡分佈式多程序在內的應用程序更加容易。
我的理解:與其說把RPC 看作是一種協議,倒不如把 它看作是一種 客戶機/服務器交互的模式,但是 RPC一定是基於 TCP 或者 其他 通信協議的
下面我們來看一下一個RPC調用的流程涉及哪些通信細節:
- 服務消費方(client)調用以本地調用方式調用服務;(1)
- client stub接收到調用後負責將方法、參數等組裝成能夠進行網絡傳輸的消息體;(2)
- client stub找到服務地址,並將消息發送到服務端;(3)
- server stub收到消息後進行解碼;(4)
- server stub根據解碼結果調用本地的服務;(5)
- 本地服務執行並將結果返回給server stub;(6)
- server stub將返回結果打包成消息併發送至消費方;(7)
- client stub接收到消息,並進行解碼;(8)
- 服務消費方得到最終結果。(9)
RPC的目標就是要2~8這些步驟都封裝起來,讓用戶對這些細節透明。
2|01.2 手動實現
1.2.1 先做一個空接口實現序列化接口
public interface IRpcService extends Serializable{ }
1.2.2 做一個需要被遠程調用的接口 以及對應的接口實現類
注:這個地方 我沒有采用dom4j 解析配置文件的形式 進行接口註冊 有時間的朋友可以多加一層
public class Client { @SuppressWarnings("unchecked") public static <T extends IRpcService>T getRemoteProxyObj(final Class<? extends IRpcService> serviceInterface,final InetSocketAddress addr){ return (T) Proxy.newProxyInstance(serviceInterface.getClassLoader(), new Class<?>[]{serviceInterface}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Socket socket = null; ObjectOutputStream output = null; ObjectInputStream input = null; try { //1.創建Socket客戶端,根據指定地址連接遠程服務提供者 socket = new Socket(); socket.connect(addr); //2.將遠程服務調用所需的接口類、方法名、參數列表等編碼後發送給服務提供者 output = new ObjectOutputStream(socket.getOutputStream()); output.writeUTF(serviceInterface.getName()); output.writeUTF(method.getName()); output.writeObject(method.getParameterTypes()); output.writeObject(args); //3.同步阻塞等待服務器返回應答 獲取應答後返回 input = new ObjectInputStream(socket.getInputStream()); return input.readObject(); } finally{ if(socket != null){ socket.close(); } if(output != null){ output.close(); } if(input != null){ input.close(); } } } }); } }
1.2.5 測試
注:測試之前 需要開啓服務端
public class RpcTest { public static void main(String[] args) throws IOException { IHelloService service = Client.getRemoteProxyObj(IHelloService.class, new InetSocketAddress(8080)); System.out.println(service.sayHi("張三", "新年快樂!")); } }
本文意在通過實現簡單的RPC,去真正意義上對RPC框架的實現原理有初步的瞭解,而不是人云亦云。
此RPC實現有諸多缺點,但是 我們只要明白RPC的基座 其他的RPC框架只是完善基座以及擴展而已 。