定義: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框架只是完善基座以及擴充套件而已 。
rpc簡單實現git程式碼地址