1. 程式人生 > >RPC( Remote Procedure Call) C++ 基礎

RPC( Remote Procedure Call) C++ 基礎

1、基礎 

prc、分散式計算

------- 下文摘自 RPC 的概念模型與實現解析 ----------

模型

1. User 2. User-stub 3. RPCRuntime 4. Server-stub 5. Server

元件

  1. RpcServer  負責匯出(export)遠端介面

  2. RpcClient  負責匯入(import)遠端介面的代理實現

  3. RpcProxy  遠端介面的代理實現

  4. RpcInvoker  客戶端:負責編碼呼叫資訊和傳送呼叫請求到服務端並等待呼叫結果返回  服務端:負責呼叫服務端介面的具體實現並返回呼叫結果

  5. RpcProtocol  負責協議編/解碼

  6. RpcConnector  負責維持客戶端和服務端的連線通道和傳送資料到服務端

  7. RpcAcceptor  負責接收客戶端請求並返回請求結果

  8. RpcProcessor  負責在服務端控制呼叫過程,包括管理呼叫執行緒池、超時時間等

  9. RpcChannel  資料傳輸通道

 協議

     協議指 RPC 呼叫在網路傳輸中約定的資料封裝方式,包括三個部分:編解碼訊息頭 和 訊息體

編解碼

       客戶端代理在發起呼叫前需要對呼叫資訊進行編碼,這就要考慮需要編碼些什麼資訊並以什麼格式傳輸到服務端才能讓服務端完成呼叫。 出於效率考慮,編碼的資訊越少越好(傳輸資料少),編碼的規則越簡單越好(執行效率高)。

我們先看下需要編碼些什麼資訊:

呼叫編碼

  1. 介面方法 

    包括介面名、方法名

  2. 方法引數 

    包括引數型別、引數值

  3. 呼叫屬性 

    包括呼叫屬性資訊,例如呼叫附加的隱式引數、呼叫超時時間等

返回編碼

  1. 返回結果 

    介面方法中定義的返回值

  2. 返回碼 

    異常返回碼

  3. 返回異常資訊 

    呼叫異常資訊

訊息頭

       除了以上這些必須的呼叫資訊,我們可能還需要一些元資訊以方便程式編解碼以及未來可能的擴充套件。這樣我們的編碼訊息裡面就分成了兩部分,一部分是元資訊、另一部分是呼叫的必要資訊。如果設計一種 RPC 協議訊息的話,元資訊我們把它放在協議訊息頭中,而必要資訊放在協議訊息體中。下面給出一種概念上的 RPC 協議訊息頭設計格式:

  1. magic 

    協議魔數,為解碼設計

  2. header size 

    協議頭長度,為擴充套件設計

  3. version 

    協議版本,為相容設計

  4. st 

    訊息體序列化型別

  5. hb 

    心跳訊息標記,為長連線傳輸層心跳設計

  6. ow 

    單向訊息標記,

  7. rp 

    響應訊息標記,不置位預設是請求訊息

  8. status code 

    響應訊息狀態碼

訊息體

訊息體常採用序列化編碼,常見有以下序列化方式:

  1. xml 

    如 webservie SOAP

  2. json 

    如 JSON-RPC

  3. binary 

    如 thrift; hession; kryo 等

格式確定後編解碼就簡單了,由於頭長度一定所以我們比較關心的就是訊息體的序列化方式。 序列化我們關心三個方面:

  1. __效率__:序列化和反序列化的效率,越快越好。

  2. __長度__:序列化後的位元組長度,越小越好。

  3. __相容__:序列化和反序列化的相容性,介面引數物件若增加了欄位,是否相容。

  4. 上面這三點有時是魚與熊掌不可兼得,這裡面涉及到具體的序列化庫實現細節,就不在本文進一步展開分析了。

傳輸

      協議編碼之後,自然就是需要將編碼後的 RPC 請求訊息傳輸到服務端,服務方執行後返回結果訊息或確認訊息給客戶端。RPC 的應用場景實質是一種可靠的請求應答訊息流,這點和 HTTP 類似。因此選擇長連線方式的 TCP 協議會更高效,與 HTTP 不同的是在協議層面我們定義了每個訊息的唯一 id,因此可以更容易的複用連線。

既然使用長連線,那麼第一個問題是到底客戶端和服務端之間需要多少根連線?實際上單連線和多連線在使用上沒有區別,對於資料傳輸量較小的應用型別,單連線基本足夠。單連線和多連線最大的區別在於,每根連線都有自己私有的傳送和接收緩衝區,因此大資料量傳輸時分散在不同的連線緩衝區會得到更好的吞吐效率。

所以,如果你的資料傳輸量不足以讓單連線的緩衝區一直處於飽和狀態的話,那麼使用多連線並不會產生任何明顯的提升,反而會增加連線管理的開銷。

連線是由客戶端發起建立並維持的,如果客戶端和服務端之間是直連的,那麼連線一般不會中斷(當然物理鏈路故障除外)。如果客戶端和服務端連線經過一些負載中轉裝置,有可能連線一段時間不活躍時會被這些中間裝置中斷。為了保持連線有必要定時為每個連線傳送心跳資料以維持連線不中斷。心跳訊息是 RPC 框架庫使用的內部訊息,在前文協議頭結構中也有一個專門的心跳位,就是用來標記心跳訊息的,它對業務應用透明。

  1. reserved 

    為位元組對齊保留

  2. message id 

    訊息 id

  3. body size 

    訊息體長 

主流RPC框架:(僅是概念)

待續