gRPC入門學習之旅(一)

DotNet菜园發表於2024-03-09

gRpc簡介

  gRPC 是Google公司開發的基於HTTP/2設計,面向移動的一個高效能、開源和通用的 RPC 框架,是一款語言中立、平臺中立、開源的遠端過程呼叫(RPC)系統。

gRpc官網地址:https://www.grpc.io

  gRpc中文文件地址:http://doc.oschina.net/grpc

  gRPC是一款RPC框架,那麼先了解Rpc是什麼。

Rpc基本概念

  RPC(Remote Procedure Call)遠端過程呼叫,是一種透過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議,簡單的理解是一個節點請求另一個節點提供的服務。RPC只是一套協議,基於這套協議規範來實現的框架都可以稱為 RPC 框架,比較典型的有 Dubbo、Thrift 和 gRPC。

  RPC 機制和實現過程
  RPC 是遠端過程呼叫的方式之一,涉及呼叫方和被呼叫方兩個程序的互動。因為 RPC 提供類似於本地方法呼叫的形式,所以對於呼叫方來說,呼叫 RPC 方法和呼叫本地方法並沒有明顯區別。

RPC的機制的誕生和基礎概念
  1984 年,Birrell 和 Nelson 在 ACM Transactions on Computer Systems 期刊上發表了名為“Implementing remote procedure calls”的論文,該文對 RPC 的機制做了經典的詮釋:
  RPC 遠端過程呼叫是指計算機 A 上的程序,呼叫另外一臺計算機 B 上的程序的方法。其中A 上面的呼叫程序被掛起,而 B 上面的被呼叫程序開始執行對應方法,並將結果返回給 A,計算機 A 接收到返回值後,呼叫程序繼續執行。

  發起 RPC 的程序透過引數等方式將資訊傳送給被呼叫方,然後被呼叫方處理結束後,再透過返回值將資訊傳遞給呼叫方。這一過程對於開發人員來說是透明的,開發人員一般也無須知道雙方底層是如何進行訊息通訊和資訊傳遞的,這樣可以讓業務開發人員更專注於業務開發,而非底層細節。

  RPC 讓程式之間的遠端過程呼叫具有與本地呼叫類似的形式。比如說某個程式需要讀取某個檔案的資料,開發人員會在程式碼中執行 read 系統呼叫來獲取資料。

  當 read 實際是本地呼叫時,read 函式由連結器從依賴庫中提取出來,接著連結器會將它連結到該程式中。雖然 read 中執行了特殊的系統呼叫,但它本身依然是透過將引數壓入堆疊的常規方式呼叫的,呼叫方並不知道 read 函式的具體實現和行為。

  當 read 實際是一個遠端過程時(比如呼叫遠端檔案伺服器提供的方法),呼叫方程式中需要引入 read 的介面定義,稱為客戶端存根(client-stub)。遠端過程 read 的客戶端存根與本地方法的 read 函式類似,都執行了本地函式呼叫。不同的是它底層實現上不是進行作業系統呼叫讀取本地檔案來提供資料,而是將引數打包成網路訊息,並將此網路訊息傳送到遠端伺服器,交由遠端服務執行對應的方法,在傳送完呼叫請求後,客戶端存根隨即阻塞,直到收到伺服器發回的響應訊息為止。


  下圖展示了遠端方法呼叫過程中的客戶端和服務端各個階段的操作。
    

                    RPC 示意圖


  當客戶端傳送請求的網路訊息到達伺服器時,伺服器上的網路服務將其傳遞給伺服器存根(server-stub)。伺服器存根與客戶端存根一一對應,是遠端方法在服務端的體現,用來將網路請求傳遞來的資料轉換為本地過程呼叫。伺服器存根一般處於阻塞狀態,等待訊息輸入。

  當伺服器存根收到網路訊息後,伺服器將方法引數從網路訊息中提取出來,然後以常規方式呼叫伺服器上對應的實現過程。從實現過程角度看,就好像是由客戶端直接呼叫一樣,引數和返回地址都位於呼叫堆疊中,一切都很正常。實現過程執行完相應的操作,隨後用得到的結果設定到堆疊中的返回值,並根據返回地址執行方法結束操作。以 read 為例,實現過程讀取本地檔案資料後,將其填充到 read 函式返回值所指向的緩衝區。

  read 過程呼叫完後,實現過程將控制權轉移給伺服器存根,它將結果(緩衝區的資料)打包為網路訊息,最後透過網路響應將結果返回給客戶端。網路響應傳送結束後,伺服器存根會再次進入阻塞狀態,等待下一個輸入的請求。

  客戶端接收到網路訊息後,客戶作業系統會將該訊息轉發給對應的客戶端存根,隨後解除對客戶程序的阻塞。客戶端存根從阻塞狀態恢復過來,將接收到的網路訊息轉換為呼叫結果,並將結果複製到客戶端呼叫堆疊的返回結果中。當呼叫者在遠端方法呼叫 read 執行完畢後重新獲得控制權時,它唯一知道的是 read 返回值已經包含了所需的資料,但並不知道該 read 操作到底是在本地作業系統讀取的檔案資料,還是透過遠端過程呼叫遠端服務讀取檔案資料。

  總結下RPC執行步驟:

  1. 呼叫客戶端控制代碼,執行傳遞引數。

  2. 呼叫本地系統核心傳送網路訊息。

  3. 訊息傳遞到遠端主機,就是被呼叫的服務端。

  4. 服務端控制代碼得到訊息並解析訊息。

  5. 服務端執行被呼叫方法,並將執行完畢的結果返回給伺服器控制代碼。

  6. 伺服器控制代碼返回結果,並呼叫遠端系統核心。

  7. 訊息經過網路傳遞給客戶端。

  8. 客戶端接受資料。



  RPC框架的組成

 一個完整的 RPC 框架包含了服務註冊發現、負載、容錯、序列化、協議編碼和網路傳輸等元件。不同的 RPC 框架包含的元件可能會有所不同,但是一定都包含 RPC 協議相關的元件,RPC 協議包括序列化、協議編解碼器和網路傳輸棧,如下圖所示:

    

  RPC 協議一般分為公有協議和私有協議。例如,HTTP、SMPP、WebService 等都是公有協議。如果是某個公司或者組織內部自定義、自己使用的,沒有被國際標準化組織接納和認可的協議,往往劃為私有協議,例如 Thrift 協議和螞蟻金服的 Bolt 協議。

  分散式架構所需要的企業內部通訊模組,往往採用私有協議來設計和研發。相較公有協議,私有協議雖然有很多弊端,比如在通用性上、公網傳輸的能力上,但是高度定製化的私有協議可以最大限度地降低成本,提升效能,提高靈活性與效率。定製私有協議,可以有效地利用協議裡的各個欄位,靈活滿足各種通訊功能需求,比如:CRC 校驗、Server Fail-Fast 機制和自定義序列化器。

  在協議設計上,你還需要考慮以下三個關鍵問題:

  1. 協議包括的必要欄位與主要業務負載欄位。協議裡設計的每個欄位都應該被使用到,避免無效欄位。
  2. 通訊功能特性的支援。比如,CRC 校驗、安全校驗、資料壓縮機制等。
  3. 協議的升級機制。畢竟是私有協議,沒有長期的驗證,欄位新增或者修改,是有可能發生的,因此升級機制是必須考慮的。

  

  RPC和HTTP區別
  RPC 和 HTTP都是微服務間通訊較為常用的方案之一,其實RPC 和 HTTP 並不完全是同一個層次的概念,它們之間還是有所區別的。
  1. RPC 是遠端過程呼叫,其呼叫協議通常包括序列化協議和傳輸協議。序列化協議有基於純文字的 XML 和 JSON、二進位制編碼的Protobuf和Hessian。傳輸協議是指其底層網路傳輸所使用的協議,比如 TCP、HTTP。
  2. 可以看出HTTP是RPC的傳輸協議的一個可選方案,比如說 gRPC 的網路傳輸協議就是 HTTP。HTTP 既可以和 RPC 一樣作為服務間通訊的解決方案,也可以作為 RPC 中通訊層的傳輸協議(此時與之對比的是 TCP 協議)。

  常見的 RPC 框架
  目前流行的開源 RPC 框架還是比較多的,有阿里巴巴的 Dubbo、Google 的 gRPC、Facebook 的 Thrift 和 Twitter 的 Finagle 等。

  1. Go RPC:Go 語言原生支援的 RPC 遠端呼叫機制,簡單便捷。
  2. gRPC:Google 釋出的開源 RPC 框架,是基於 HTTP 2.0 協議的,並支援眾多常見的程式語言,它提供了強大的流式呼叫能力,目前已經成為最主流的 RPC 框架之一。
  3. Thrift:Facebook 的開源 RPC 框架,主要是一個跨語言的服務開發框架,作為老牌開源 RPC 協議,以其高效能和穩定性成為眾多開源專案提供資料的方案選項。

相關文章