本文來自於Dubbo官網: 淺談 RPC,轉載請保留連接 ;)
近幾年隨着微服務化項目的崛起,逐漸成爲許多公司中大型分佈式系統架構的主流方式,而今天所說的 RPC 在這其中扮演着相當重要的角色。隨着這段日子公司項目微服務化的演進,發如今平常開發中都在隱式或顯式的使用 RPC,一些剛剛接觸 RPC 的小夥伴會感受無所適從,而一些入行多年的老手雖然使用 RPC 經驗豐富,但有些對其原理也只知其一;不知其二,缺少對原理的深刻理解,每每也會形成開發中的一些誤用。html
RPC(Remote Procedure Call)—遠程過程調用,它是一種經過網絡從遠程計算機程序上請求服務,而不須要了解底層網絡技術的協議。也就是說兩臺服務器A,B,一個應用部署在A服務器上,想要調用B服務器上應用提供的方法,因爲不在一個內存空間,不能直接調用,須要經過網絡來表達調用的語義和傳達調用的數據。程序員
RPC協議假定某些傳輸協議的存在,如TCP或UDP,爲通訊程序之間攜帶信息數據。在OSI網絡通訊模型中,RPC跨越了傳輸層和應用層。RPC使得開發包括網絡分佈式多程序在內的應用程序更加容易。如今業界有不少開源的優秀 RPC 框架,例如 Spring Cloud、Dubbo、Thrift 等。算法
RPC 這個概念術語在上世紀 80 年代由 Bruce Jay Nelson 提出。這裏咱們追溯下當初開發 RPC 的原動機是什麼?在 Nelson 的論文 "Implementing Remote Procedure Calls" 中他提到了幾點:apache
通俗一點說,就是通常程序員對於本地的過程調用很熟悉,那麼咱們把 RPC 做成和本地調用徹底相似,那麼就更容易被接受,使用起來毫無障礙。Nelson 的論文發表於 30 年前,其觀點今天看來確實高瞻遠矚,今天咱們使用的 RPC 框架基本就是按這個目標來實現的。服務器
Nelson 的論文中指出實現 RPC 的程序包括 5 個部分:網絡
這裏 user 就是 client 端,當 user 想發起一個遠程調用時,它實際是經過本地調用 user-stub。user-stub 負責將調用的接口、方法和參數經過約定的協議規範進行編碼並經過本地的 RPCRuntime 實例傳輸到遠端的實例。遠端 RPCRuntime 實例收到請求後交給 server-stub 進行解碼後發起本地端調用,調用結果再返回給 user 端。架構
以上是粗粒度的 RPC 實現概念結構,接下來咱們進一步細化它應該由哪些組件構成,以下圖所示。負載均衡
RPC 服務方經過 RpcServer 去導出(export)遠程接口方法,而客戶方經過 RpcClient 去引入(import)遠程接口方法。客戶方像調用本地方法同樣去調用遠程接口方法,RPC 框架提供接口的代理實現,實際的調用將委託給代理RpcProxy 。代理封裝調用信息並將調用轉交給RpcInvoker 去實際執行。在客戶端的RpcInvoker 經過鏈接器RpcConnector 去維持與服務端的通道RpcChannel,並使用RpcProtocol 執行協議編碼(encode)並將編碼後的請求消息經過通道發送給服務方。框架
RPC 服務端接收器 RpcAcceptor 接收客戶端的調用請求,一樣使用RpcProtocol 執行協議解碼(decode)。解碼後的調用信息傳遞給RpcProcessor 去控制處理調用過程,最後再委託調用給RpcInvoker 去實際執行並返回調用結果。以下是各個部分的詳細職責:異步
1. RpcServer 負責導出(export)遠程接口 2. RpcClient 負責導入(import)遠程接口的代理實現 3. RpcProxy 遠程接口的代理實現 4. RpcInvoker 客戶方實現:負責編碼調用信息和發送調用請求到服務方並等待調用結果返回 服務方實現:負責調用服務端接口的具體實現並返回調用結果 5. RpcProtocol 負責協議編/解碼 6. RpcConnector 負責維持客戶方和服務方的鏈接通道和發送數據到服務方 7. RpcAcceptor 負責接收客戶方請求並返回請求結果 8. RpcProcessor 負責在服務方控制調用過程,包括管理調用線程池、超時時間等 9. RpcChannel 數據傳輸通道
RPC的設計由Client,Client stub,Network ,Server stub,Server構成。 其中Client就是用來調用服務的,Cient stub是用來把調用的方法和參數序列化的(由於要在網絡中傳輸,必需要把對象轉變成字節),Network用來傳輸這些信息到Server stub, Server stub用來把這些信息反序列化的,Server就是服務的提供者,最終調用的就是Server提供的方法。
RPC 調用分如下兩種:
異步和同步的區分在因而否等待服務端執行完成並返回結果。
RPC 的主要功能目標是讓構建分佈式計算(應用)更容易,在提供強大的遠程調用能力時不損失本地調用的語義簡潔性。爲實現該目標,RPC 框架需提供一種透明調用機制,讓使用者沒必要顯式的區分本地調用和遠程調用,在以前給出的一種實現結構,基於 stub 的結構來實現。下面咱們將具體細化 stub 結構的實現。
RPC的目的是讓你在本地調用遠程的方法,而對你來講這個調用是透明的,你並不知道這個調用的方法是部署哪裏。經過RPC能解耦服務,這纔是使用RPC的真正目的。
這篇文章介紹了 RPC 的一些基本原理,相信到這裏您已經對 RPC 有了必定理解。其實發現實現一個 RPC 不算難,難的是實現一個高性能高可靠的RPC框架。好比,既然是分佈式了,那麼一個服務可能有多個實例,你在調用時,要如何獲取這些實例的地址呢?這時候就須要一個服務註冊中心,好比在Dubbo中,就可使用Zookeeper做爲註冊中心,在調用時,從Zookeeper獲取服務的實例列表,再從中選擇一個進行調用。那麼選哪一個調用好呢?這時候就須要負載均衡了,因而你又得考慮如何實現複雜均衡,好比Dubbo就提供了好幾種負載均衡策略。因此請繼續關注個人另外兩篇文章RPC與服務化的關係和註冊中心,配置中心, 服務發現淺談,相信會幫助對RPC設計和實現有更多的理解。