RPC英文全稱remote procedure call 翻譯成中文的意思就是遠程過程調用。RPC的出現其實主要是為了解決分布式系統間的通信透明性的問題。
那什么是分布式系統的通信透明性問題?這個問題就是指分布式系統間的相互調用其實是基本進程間的顯式消息交換,然而,消息的發送和接收過程無法隱藏。而通信的隱藏對於分布式中實現訪問的透明性是極為重要的。試想一下比如你要想查看一個訂單詳情,然后訂單系統部署了三台機器。假設沒有RPC,其它系統想通過調訂單系統查詢訂單詳情的信息,就必須知道訂單系統部署機器的ip和端口,每個調用者必須關注訂單系統新加或者下線和換機器部署等情景。試想這對調用者來說是有多蛋疼。換言之分布式系統通信就應該是透明的,這樣調用者就不需要關心調用的是那台機器上面的服務。在調用者的角度這個遠程服務應該和調用本地服務一樣是一個單一穩定可靠的服務。
基於這樣的背景有人就提出了一種與傳統方法截然不同的通信手段:不同機器上的進程是允許相與調用的,當機器A上的進程調用機器B上的進程時,A上的調用進程被掛起,而B上的被調用進程開始執行。調用方可以通過使用參數將信息傳送給被調用方,然后可以通過傳回的結果得到信息。編程人員看不到任何消息傳遞過程。這個方法就被程為遠程過程調用RPC.
在介紹RPC之前我們先來看常規過程調用。比如我們定義一個c語言的方法
count = read(fd,buf,nbytes); 這里fd為一個整形數,表示一個文件,buf為一個字符數組,用於存儲讀入的數據,nbytes為另一個整數,用於記錄實際讀入的字節數。當在主程序調用這個方法時實際的執行過程是先把參數壓入堆棧中

然后程序讀取堆棧里面的參數,執行系統的庫函數,其中還包括執行線程從用戶態到內核態的切換,執行完畢后又從內核態到用戶態的轉換過程。這些於調用者來說都是不可見和不用關心的。
RPC的設計思想其實與常規過程調用類似,屏蔽底層的細節使程序不知道調用的業務邏輯是在另一台機器上面處理的使其專注於自身業務邏輯處理。正常的RPC調用過程

舉一個遠程調用兩個數求和的詳細調用過程

這里面出現了兩個名詞客戶端存根、服務端存根。 其實客戶端存根指的就是我們現在RPC框架中的client端,服務端存根就是server端,只是不叫法而已。客戶端存根的作用是把請求的參數以約定的通訊協議打包好發送給服務端然后解析服務端返回消息,服務端存根就是根據收到的請求信息執行相應的業務邏輯調用並把結果返回客戶端。要定義一個RPC框架首先要定義好通訊格式,因為最絡從網絡層解析出來的數據都是以字符串的形式解析出來的.我們需要從這一串字符中解析出調用哪個服務,服務入參是什么。
一般來說客戶端存根會把調用類名稱傳給服務端,服務端存根根據這個名稱找到對應的service的映射,就知道調哪個服務了。所以服務端存根要保存一份service的映射關系。同樣客戶端存根收到響應后會喚醒之前調用的線程或者等待之前的線程運行處理返回的結果。
解決了RPC的調用問題,現在還要解決的一個關鍵問題是,客戶端怎么知道調用哪一台機器上的服務。這就需要引入一個中間的第三者目標服務器。

服務提供者向目標服務器注冊服務,客戶機從目標服務器(一種叫法叫服務注冊中心)中獲取可調用的機器列表。如果有用過類似dubbo這樣的RPC框架是不是對這個圖很熟悉?因為所有的RPC架構的原理大多都是類似的。服務提供者往目標服務器里面通常會注冊機器的ip和端口信息。
下面我們來談下RPC的好處和注意的地方。
好處:屏蔽了底層通訊的復雜性,在分布式系統中提供了通訊的透明性。
需要注意的地方:RPC是點對點的通訊方式,要求通訊兩端必須同時運行,當其中一端掛了就會導致通常異常,並且調用者一般會阻塞住等待結果的返回,性能相對不是很高,當然也有異步RPC,超時重試情況下服務端提供者需要做好服務冪等性處理。相對於RPC而言采用了面向消息通訊模型的架構比如MQ則不要求通訊兩端同時運行,發送消息時也不需要阻塞等待處理結果的返回通訊性能就高出很多。
最后我們總結一下:RPC調用是指不同機器間的進程通訊。程序不需要關心某個遠程服務是在哪台機器上執行的,遠程服務調用就和調用本地服務一樣。要在不同機器間進行通訊我們需要知道通訊機器的ip和端口號。ip幫助我們定位是哪一台機器,端口號幫我們定位是機器上的哪一個進程。RPC的出現使用得機器的進程通訊透明化,這在分布式系統中是很重要的。RPC調用架構中客戶端和服務端都和一個叫服務注冊中心的第三方通訊。
