RPC非常重要,很多人面試的時候都掛在了這個地方!你要是還不懂RPC是什么?他的基本原理是什么?你一定要把下邊的內(nèi)容記起來!好好研究一下!特別是文中給出的一張關于RPC的基本流程圖,重點中的重點,Dubbo RPC的基本執(zhí)行流程就是他,RPC框架的基本原理也是他,別說我沒告訴你!看了下邊的內(nèi)容你要掌握的內(nèi)容如下,當然還有很多:
RPC的由來,是怎樣一步步演進出來的;
RPC的基本架構(gòu)是什么;
RPC的基本實現(xiàn)原理,就是下邊的這張圖,重點中的重點;
REST 和 SOAP、RPC 有何區(qū)別呢?
整個調(diào)用的過程經(jīng)歷了哪幾步和Spring MVC的執(zhí)行流程一樣,相當重要;
一、為什么要有RPC
隨著互聯(lián)網(wǎng)的發(fā)展,網(wǎng)站應用的規(guī)模不斷擴大,常規(guī)的垂直應用架構(gòu)已無法應對,分布式服務架構(gòu)以及流動計算架構(gòu)勢在必行,亟需一個治理系統(tǒng)確保架構(gòu)有條不紊的演進。
1、單一應用架構(gòu)
當網(wǎng)站流量很小時,只需一個應用,將所有功能都部署在一起,以減少部署節(jié)點和成本。此時,用于簡化增刪改查工作量的數(shù)據(jù)訪問框架(ORM) 是關鍵。
2、垂直應用架構(gòu)
當訪問量逐漸增大,單一應用增加機器帶來的加速度越來越小,將應用拆成互不相干的幾個應用,以提升效率。此時,用于加速前端頁面開發(fā)的 Web框架(MVC) 是關鍵。
3、分布式服務架構(gòu)
當垂直應用越來越多,Java進階交流群851531810應用之間交互不可避免,將核心業(yè)務抽取出來,作為獨立的服務,逐漸形成穩(wěn)定的服務中心,使前端應用能更快速的響應多變的市場需求。
此時,用于提高業(yè)務復用及整合的分布式服務框架(RPC),提供統(tǒng)一的服務是關鍵。
例如:各個團隊的服務提供方就不要各自實現(xiàn)一套序列化、反序列化、網(wǎng)絡框架、連接池、收發(fā)線程、超時處理、狀態(tài)機等“業(yè)務之外”的重復技術勞動,造成整體的低效。
PS:其實上述三個原因也是為什么要有Dubbo的原因!不信你去Dubbo官網(wǎng)去看!
流動計算架構(gòu)
PS:這個屬于擴展內(nèi)容,摘自Dubbo官網(wǎng),屬于架構(gòu)演進的一個過程
當服務越來越多,容量的評估,小服務資源的浪費等問題逐漸顯現(xiàn),此時需增加一個調(diào)度中心基于訪問壓力實時管理集群容量,提高集群利用率。此時,用于提高機器利用率的資源調(diào)度和治理中心(SOA)是關鍵。
4、另外一個原因
就是因為在幾個進程內(nèi)(應用分布在不同的機器上),無法共用內(nèi)存空間,或者在一臺機器內(nèi)通過本地調(diào)用無法完成相關的需求,比如不同的系統(tǒng)之間的通訊,甚至不同組織之間的通訊。此外由于機器的橫向擴展,需要在多臺機器組成的集群上部署應用等等。
所以,統(tǒng)一RPC框架來解決提供統(tǒng)一的服務。
二、什么是RPC
RPC(Remote Procedure Call Protocol)遠程過程調(diào)用協(xié)議,它是一種通過網(wǎng)絡從遠程計算機程序上請求服務,而不需要了解底層網(wǎng)絡技術的協(xié)議。簡言之,RPC使得程序能夠像訪問本地系統(tǒng)資源一樣,去訪問遠端系統(tǒng)資源。比較關鍵的一些方面包括:通訊協(xié)議、序列化、資源(接口)描述、服務框架、性能、語言支持等。
簡單的說,RPC就是從一臺機器(客戶端)上通過參數(shù)傳遞的方式調(diào)用另一臺機器(服務器)上的一個函數(shù)或方法(可以統(tǒng)稱為服務)并得到返回的結(jié)果。
三、PRC架構(gòu)組件
一個基本的RPC架構(gòu)里面應該至少包含以下4個組件:
1、客戶端(Client):服務調(diào)用方(服務消費者)
2、客戶端存根(Client Stub):存放服務端地址信息,將客戶端的請求參數(shù)數(shù)據(jù)信息打包成網(wǎng)絡消息,再通過網(wǎng)絡傳輸發(fā)送給服務端
3、服務端存根(Server Stub):接收客戶端發(fā)送過來的請求消息并進行解包,然后再調(diào)用本地服務進行處理
4、服務端(Server):服務的真正提供者
具體調(diào)用過程:
1、服務消費者(client客戶端)通過調(diào)用本地服務的方式調(diào)用需要消費的服務;
2、客戶端存根(client stub)接收到調(diào)用請求后負責將方法、入?yún)⒌刃畔⑿蛄谢ńM裝)成能夠進行網(wǎng)絡傳輸?shù)南Ⅲw;
3、客戶端存根(client stub)找到遠程的服務地址,并且將消息通過網(wǎng)絡發(fā)送給服務端;
4、服務端存根(server stub)收到消息后進行解碼(反序列化操作);
5、服務端存根(server stub)根據(jù)解碼結(jié)果調(diào)用本地的服務進行相關處理;
6、本地服務執(zhí)行具體業(yè)務邏輯并將處理結(jié)果返回給服務端存根(server stub);
7、服務端存根(server stub)將返回結(jié)果重新打包成消息(序列化)并通過網(wǎng)絡發(fā)送至消費方;
8、客戶端存根(client stub)接收到消息,并進行解碼(反序列化);
9、服務消費方得到最終結(jié)果;
而RPC框架的實現(xiàn)目標則是將上面的第2-10步完好地封裝起來,也就是把調(diào)用、編碼/解碼的過程給封裝起來,讓用戶感覺上像調(diào)用本地服務一樣的調(diào)用遠程服務。
四、RPC和SOA、SOAP、REST的區(qū)別
1、REST
可以看著是HTTP協(xié)議的一種直接應用,默認基于JSON作為傳輸格式,使用簡單,學習成本低效率高,但是安全性較低。
2、SOAP
SOAP是一種數(shù)據(jù)交換協(xié)議規(guī)范,是一種輕量的、簡單的、基于XML的協(xié)議的規(guī)范。而SOAP可以看著是一個重量級的協(xié)議,基于XML、SOAP在安全方面是通過使用XML-Security和XML-Signature兩個規(guī)范組成了WS-Security來實現(xiàn)安全控制的,當前已經(jīng)得到了各個廠商的支持 。
它有什么優(yōu)點?簡單總結(jié)為:易用、靈活、跨語言、跨平臺。
3、SOA
面向服務架構(gòu),它可以根據(jù)需求通過網(wǎng)絡對松散耦合的粗粒度應用組件進行分布式部署、組合和使用。服務層是SOA的基礎,可以直接被應用調(diào)用,Java進階交流群851531810從而有效控制系統(tǒng)中與軟件代理交互的人為依賴性。
SOA是一種粗粒度、松耦合服務架構(gòu),服務之間通過簡單、精確定義接口進行通訊,不涉及底層編程接口和通訊模型。SOA可以看作是B/S模型、XML(標準通用標記語言的子集)/Web Service技術之后的自然延伸。
4、REST 和 SOAP、RPC 有何區(qū)別呢?
沒什么太大區(qū)別,他們的本質(zhì)都是提供可支持分布式的基礎服務,最大的區(qū)別在于他們各自的的特點所帶來的不同應用場景 。
五、RPC框架需要解決的問題?
1、如何確定客戶端和服務端之間的通信協(xié)議?
2、如何更高效地進行網(wǎng)絡通信?
3、服務端提供的服務如何暴露給客戶端?
4、客戶端如何發(fā)現(xiàn)這些暴露的服務?
5、如何更高效地對請求對象和響應結(jié)果進行序列化和反序列化操作?
六、RPC的實現(xiàn)基礎?
1、需要有非常高效的網(wǎng)絡通信,比如一般選擇Netty作為網(wǎng)絡通信框架;
2、需要有比較高效的序列化框架,比如谷歌的Protobuf序列化框架;
3、可靠的尋址方式(主要是提供服務的發(fā)現(xiàn)),Java進階交流群851531810比如可以使用Zookeeper來注冊服務等等;
4、如果是帶會話(狀態(tài))的RPC調(diào)用,還需要有會話和狀態(tài)保持的功能;
七、RPC使用了哪些關鍵技術?
1、動態(tài)代理
生成Client Stub(客戶端存根)和Server Stub(服務端存根)的時候需要用到Java動態(tài)代理技術,可以使用JDK提供的原生的動態(tài)代理機制,也可以使用開源的:CGLib代理,Javassist字節(jié)碼生成技術。
2、序列化和反序列化
在網(wǎng)絡中,所有的數(shù)據(jù)都將會被轉(zhuǎn)化為字節(jié)進行傳送,所以為了能夠使參數(shù)對象在網(wǎng)絡中進行傳輸,需要對這些參數(shù)進行序列化和反序列化操作。
序列化:把對象轉(zhuǎn)換為字節(jié)序列的過程稱為對象的序列化,也就是編碼的過程。
反序列化:把字節(jié)序列恢復為對象的過程稱為對象的反序列化,也就是解碼的過程。
目前比較高效的開源序列化框架:如Kryo、FastJson和Protobuf等。
3、NIO通信
出于并發(fā)性能的考慮,傳統(tǒng)的阻塞式 IO 顯然不太合適,因此我們需要異步的 IO,即 NIO。Java 提供了 NIO 的解決方案,Java 7 也提供了更優(yōu)秀的 NIO.2 支持。可以選擇Netty或者MINA來解決NIO數(shù)據(jù)傳輸?shù)膯栴}。
4、服務注冊中心
可選:Redis、Zookeeper、Consul 、Etcd。一般使用ZooKeeper提供服務注冊與發(fā)現(xiàn)功能,解決單點故障以及分布式部署的問題(注冊中心)。
八、主流RPC框架有哪些
1、RMI
利用java.rmi包實現(xiàn),基于Java遠程方法協(xié)議(Java Remote Method Protocol) 和java的原生序列化。
2、Hessian
是一個輕量級的remoting onhttp工具,使用簡單的方法提供了RMI的功能。 基于HTTP協(xié)議,采用二進制編解碼。
3、protobuf-rpc-pro
是一個Java類庫,提供了基于 Google 的 Protocol Buffers 協(xié)議的遠程方法調(diào)用的框架?;?Netty 底層的 NIO 技術。支持 TCP 重用/ keep-alive、SSL加密、RPC 調(diào)用取消操作、嵌入式日志等功能。
4、Thrift
是一種可伸縮的跨語言服務的軟件框架。它擁有功能強大的代碼生成引擎,無縫地支持C + +,C#,Java,Python和PHP和Ruby。thrift允許你定義一個描述文件,描述數(shù)據(jù)類型和服務接口。依據(jù)該文件,編譯器方便地生成RPC客戶端和服務器通信代碼。
最初由facebook開發(fā)用做系統(tǒng)內(nèi)個語言之間的RPC通信,2007年由facebook貢獻到apache基金 ,現(xiàn)在是apache下的opensource之一 。支持多種語言之間的RPC方式的通信:php語言client可以構(gòu)造一個對象,調(diào)用相應的服務方法來調(diào)用java語言的服務,跨越語言的C/S RPC調(diào)用。底層通訊基于SOCKET。
5、Avro
出自Hadoop之父Doug Cutting, 在Thrift已經(jīng)相當流行的情況下推出Avro的目標不僅是提供一套類似Thrift的通訊中間件,更是要建立一個新的,標準性的云計算的數(shù)據(jù)交換和存儲的Protocol。支持HTTP,TCP兩種協(xié)議。
6、Dubbo
Dubbo是 阿里巴巴公司開源的一個高性能優(yōu)秀的服務框架,使得應用可通過高性能的 RPC 實現(xiàn)服務的輸出和輸入功能,可以和 Spring框架無縫集成。
九、RPC的實現(xiàn)原理架構(gòu)圖
PS:這張圖非常重點,是PRC的基本原理,請大家一定記住!
也就是說兩臺服務器A,B,一個應用部署在A服務器上,想要調(diào)用B服務器上應用提供的函數(shù)/方法,由于不在一個內(nèi)存空間,不能直接調(diào)用,需要通過網(wǎng)絡來表達調(diào)用的語義和傳達調(diào)用的數(shù)據(jù)。
Java進階交流群851531810
比如說,A服務器想調(diào)用B服務器上的一個方法:
User getUserByName(String userName)
1、建立通信
首先要解決通訊的問題:即A機器想要調(diào)用B機器,首先得建立起通信連接。
主要是通過在客戶端和服務器之間建立TCP連接,遠程過程調(diào)用的所有交換的數(shù)據(jù)都在這個連接里傳輸。連接可以是按需連接,調(diào)用結(jié)束后就斷掉,也可以是長連接,多個遠程過程調(diào)用共享同一個連接。
通常這個連接可以是按需連接(需要調(diào)用的時候就先建立連接,調(diào)用結(jié)束后就立馬斷掉),也可以是長連接(客戶端和服務器建立起連接之后保持長期持有,不管此時有無數(shù)據(jù)包的發(fā)送,可以配合心跳檢測機制定期檢測建立的連接是否存活有效),多個遠程過程調(diào)用共享同一個連接。
2、服務尋址
要解決尋址的問題,也就是說,A服務器上的應用怎么告訴底層的RPC框架,如何連接到B服務器(如主機或IP地址)以及特定的端口,方法的名稱名稱是什么。
通常情況下我們需要提供B機器(主機名或IP地址)以及特定的端口,然后指定調(diào)用的方法或者函數(shù)的名稱以及入?yún)⒊鰠⒌刃畔ⅲ@樣才能完成服務的一個調(diào)用。
可靠的尋址方式(主要是提供服務的發(fā)現(xiàn))是RPC的實現(xiàn)基石,比如可以采用Redis或者Zookeeper來注冊服務等等。
2.1、從服務提供者的角度看:
當服務提供者啟動的時候,需要將自己提供的服務注冊到指定的注冊中心,以便服務消費者能夠通過服務注冊中心進行查找;
當服務提供者由于各種原因致使提供的服務停止時,需要向注冊中心注銷停止的服務;
服務的提供者需要定期向服務注冊中心發(fā)送心跳檢測,服務注冊中心如果一段時間未收到來自服務提供者的心跳后,認為該服務提供者已經(jīng)停止服務,則將該服務從注冊中心上去掉。
2.2、從調(diào)用者的角度看:
服務的調(diào)用者啟動的時候根據(jù)自己訂閱的服務向服務注冊中心查找服務提供者的地址等信息;
當服務調(diào)用者消費的服務上線或者下線的時候,注冊中心會告知該服務的調(diào)用者;
服務調(diào)用者下線的時候,則取消訂閱。
3、網(wǎng)絡傳輸
3.1、序列化
當A機器上的應用發(fā)起一個RPC調(diào)用時,調(diào)用方法和其入?yún)⒌刃畔⑿枰ㄟ^底層的網(wǎng)絡協(xié)議如TCP傳輸?shù)紹機器,由于網(wǎng)絡協(xié)議是基于二進制的,所有我們傳輸?shù)膮?shù)數(shù)據(jù)都需要先進行序列化(Serialize)或者編組(marshal)成二進制的形式才能在網(wǎng)絡中進行傳輸。然后通過尋址操作和網(wǎng)絡傳輸將序列化或者編組之后的二進制數(shù)據(jù)發(fā)送給B機器。
3.2、反序列化
當B機器接收到A機器的應用發(fā)來的請求之后,又需要對接收到的參數(shù)等信息進行反序列化操作(序列化的逆操作),即將二進制信息恢復為內(nèi)存中的表達方式,然后再找到對應的方法(尋址的一部分)進行本地調(diào)用(一般是通過生成代理Proxy去調(diào)用,
通常會有JDK動態(tài)代理、CGLIB動態(tài)代理、Javassist生成字節(jié)碼技術等),之后得到調(diào)用的返回值。
4、服務調(diào)用
B機器進行本地調(diào)用(通過代理Proxy和反射調(diào)用)之后得到了返回值,此時還需要再把返回值發(fā)送回A機器,同樣也需要經(jīng)過序列化操作,然后再經(jīng)過網(wǎng)絡傳輸將二進制數(shù)據(jù)發(fā)送回A機器,而當A機器接收到這些返回值之后,則再次進行反序列化操作,恢復為內(nèi)存中的表達方式,最后再交給A機器上的應用進行相關處理(一般是業(yè)務邏輯處理操作)。
通常,經(jīng)過以上四個步驟之后,一次完整的RPC調(diào)用算是完成了,另外可能因為網(wǎng)絡抖動等原因需要重試等。
最后,給大家推薦一個Java進階交流群851531810,不管你在地球哪個方位,不管你參加工作幾年都歡迎你的入駐!(群內(nèi)會免費提供一些群主收藏的免費學習書籍資料以及整理好的幾百道面試題和答案文檔?。?/p>