RPC概述
RPC(Remote Procedure Call)即遠程過程調(diào)用,允許一臺計算機調(diào)用另一臺計算機上的程序得到結(jié)果,而代碼中不需要做額外的編程,就像在本地調(diào)用一樣。
現(xiàn)在互聯(lián)網(wǎng)應(yīng)用的量級越來越大,單臺計算機的能力有限,需要借助可擴展的計算機集群來完成,分布式的應(yīng)用可以借助RPC來完成機器之間的調(diào)用。
RPC框架原理
在RPC框架中主要有三個角色:Provider、Consumer和Registry。如下圖所示:
節(jié)點角色說明:
* Server: 暴露服務(wù)的服務(wù)提供方。
* Client: 調(diào)用遠程服務(wù)的服務(wù)消費方。
* Registry: 服務(wù)注冊與發(fā)現(xiàn)的注冊中心。
RPC調(diào)用流程
RPC基本流程圖:
一次完整的RPC調(diào)用流程(同步調(diào)用,異步另說)如下:
1)服務(wù)消費方(client)調(diào)用以本地調(diào)用方式調(diào)用服務(wù);
2)client stub接收到調(diào)用后負責(zé)將方法、參數(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ù)執(zhí)行并將結(jié)果返回給server stub;
7)server stub將返回結(jié)果打包成消息并發(fā)送至消費方;
8)client stub接收到消息,并進行解碼;
9)服務(wù)消費方得到最終結(jié)果。
RPC框架的目標就是要2~8這些步驟都封裝起來,讓用戶對這些細節(jié)透明。
服務(wù)注冊&發(fā)現(xiàn)
服務(wù)提供者啟動后主動向注冊中心注冊機器ip、port以及提供的服務(wù)列表;
服務(wù)消費者啟動時向注冊中心獲取服務(wù)提供方地址列表,可實現(xiàn)軟負載均衡和Failover;
使用到的技術(shù)
1、動態(tài)代理
生成 client stub和server stub需要用到 Java 動態(tài)代理技術(shù) ,我們可以使用JDK原生的動態(tài)代理機制,可以使用一些開源字節(jié)碼工具框架 如:CgLib、Javassist等。
2、序列化
為了能在網(wǎng)絡(luò)上傳輸和接收 Java對象,我們需要對它進行 序列化和反序列化操作。
* 序列化:將Java對象轉(zhuǎn)換成byte[]的過程,也就是編碼的過程;
* 反序列化:將byte[]轉(zhuǎn)換成Java對象的過程;
可以使用Java原生的序列化機制,但是效率非常低,推薦使用一些開源的、成熟的序列化技術(shù),例如:protobuf、Thrift、hessian、Kryo、Msgpack
關(guān)于序列化工具性能比較可以參考:jvm-serializers
3、NIO
當(dāng)前很多RPC框架都直接基于netty這一IO通信框架,比如阿里巴巴的HSF、dubbo,Hadoop Avro,推薦使用Netty 作為底層通信框架。
4、服務(wù)注冊中心
可選技術(shù):
* Redis
* Zookeeper
* Consul
* Etcd
編程實踐
本人基于 Netty4 + Zookeeper + protostuff + Spring 實現(xiàn)了一個簡單、高效的RPC框架Mango:https://github.com/TiFG/mango,歡迎大家fork/star。
開源的優(yōu)秀RPC框架
阿里巴巴 Dubbo:https://github.com/alibaba/dubbo
新浪微博 Motan:https://github.com/weibocom/motan
gRPC:https://github.com/grpc/grpc
rpcx :https://github.com/smallnest/rpcx
Apache Thrift :https://thrift.apache.org/