谷歌開源的高性能 RPC 框架gRPC

gRPC概述

gRPC 一開始由 google 開發,是一款語言中立、平臺中立、開源的遠程過程調用(RPC)系統。gRPC 是一個高性能、開源和通用的 RPC 框架,面向移動和 HTTP/2 設計。目前提供 C、Java 和 Go 語言版本,分別是:grpc, grpc-java, grpc-go。gRPC 基於 HTTP/2 標準設計,帶來諸如雙向流、流控、頭部壓縮、單 TCP 連接上的多複用請求等特性。這些特性使得其在移動設備上表現更好,更省電和節省空間佔用。

所謂RPC(remote procedure call,遠程過程調用)框架實際是提供了一套機制,使得應用程序之間可以進行通信,而且也遵從server/client模型。在 gRPC 裡客戶端應用可以像調用本地對象一樣直接調用另一臺不同的機器上服務端應用的方法,使得您能夠更容易地創建分佈式應用和服務。與許多 RPC 系統類似,gRPC 也是基於以下理念:定義一個服務,指定其能夠被遠程調用的方法(包含參數和返回類型)。在服務端實現這個接口,並運行一個 gRPC 服務器來處理客戶端調用。在客戶端擁有一個存根能夠像服務端一樣的方法。

谷歌開源的高性能 RPC 框架gRPC

gRPC 客戶端和服務端可以在多種環境中運行和交互。從 google 內部的服務器到你自己的筆記本,並且可以用任何 gRPC 支持的語言來編寫。所以,你可以很容易地用 Java 創建一個 gRPC 服務端,用 Go、Python、Ruby 來創建客戶端。此外,Google 最新 API 將有 gRPC 版本的接口,使你很容易地將 Google 的功能集成到你的應用裡。

gRPC 默認使用 protocol buffers,這是 Google 開源的一套成熟的結構數據序列化機制(當然也可以使用其他數據格式如 JSON)。用戶可用 proto files 創建 gRPC 服務,用 protocol buffers 消息類型來定義方法參數和返回類型。

gRPC 概念

服務定義

正如其他 RPC 系統,gRPC 基於如下思想:定義一個服務, 指定其可以被遠程調用的方法及其參數和返回類型。gRPC 默認使用 protocol buffers 作為接口定義語言,來描述服務接口和有效載荷消息結構。如果有需要的話,可以使用其他替代方案。gRPC 提供 protocol buffer 編譯插件,能夠從一個服務定義的 .proto 文件生成客戶端和服務端代碼。通常 gRPC 用戶可以在服務端實現這些API,並從客戶端調用它們。

  • 在服務側,服務端實現服務接口,運行一個 gRPC 服務器來處理客戶端調用。gRPC 底層架構會解碼傳入的請求,執行服務方法,編碼服務應答。
  • 在客戶側,客戶端有一個存根實現了服務端同樣的方法。客戶端可以在本地存根調用這些方法,用合適的 protocol buffer 消息類型封裝這些參數— gRPC 來負責發送請求給服務端並返回服務端 protocol buffer 響應。

同步 vs 異步

同步 RPC 調用一直會阻塞直到從服務端獲得一個應答,這與 RPC 希望的抽象最為接近。另一方面網絡內部是異步的,並且在許多場景下能夠在不阻塞當前線程的情況下啟動 RPC 是非常有用的。在多數語言裡,gRPC 編程接口同時支持同步和異步的特點。

RPC 生命週期

單項 RPC

最簡單的 RPC 形式:客戶端發出單個請求,獲得單個響應。

  • 一旦客戶端通過樁調用一個方法,服務端會得到相關通知 ,通知包括客戶端的元數據,方法名,允許的響應期限
  • 服務端既可以在任何響應之前直接發送回初始的元數據,也可以等待客戶端的請求信息,到底哪個先發生,取決於具體的應用。
  • 一旦服務端獲得客戶端的請求信息,就會做所需的任何工作來創建或組裝對應的響應。如果成功的話,這個響應會和包含狀態碼以及可選的狀態信息等狀態明細及可選的追蹤信息返回給客戶端 。
  • 假如狀態是 OK 的話,客戶端會得到應答,這將結束客戶端的調用。

服務端流式 RPC

服務端流式 RPC 除了在得到客戶端請求信息後發送回一個應答流之外,在發送完所有應答後,服務端的狀態詳情(狀態碼和可選的狀態信息)和可選的跟蹤元數據被髮送回客戶端,以此來完成服務端的工作。客戶端在接收到所有服務端的應答後也完成了工作。

客戶端流式 RPC

客戶端流式 RPC 區別在於客戶端通過發送一個請求流給服務端,取代了原先發送的單個請求。服務端通常(但並不必須)會在接收到客戶端所有的請求後發送回一個應答,其中附帶有它的狀態詳情和可選的跟蹤數據。

雙向流式 RPC

雙向流式 RPC ,調用由客戶端調用方法來初始化,而服務端則接收到客戶端的元數據,方法名和截止時間。服務端可以選擇發送回它的初始元數據或等待客戶端發送請求。下一步怎樣發展取決於應用,因為客戶端和服務端能在任意順序上讀寫 - 這些流的操作是完全獨立的。例如服務端可以一直等直到它接收到所有客戶端的消息才寫應答,或者服務端和客戶端可以像"乒乓球"一樣:服務端後得到一個請求就回送一個應答,接著客戶端根據應答來發送另一個請求,以此類推。

截止時間

gRPC 允許客戶端在調用一個遠程方法前指定一個最後期限值。這個值指定了在客戶端可以等待服務端多長時間來應答,超過這個時間值 RPC 將結束並返回DEADLINE_EXCEEDED錯誤。在服務端可以查詢這個期限值來看是否一個特定的方法已經過期,或者還剩多長時間來完成這個方法。各語言來指定一個截止時間的方式是不同的 - 比如在 Python 裡一個截止時間值總是必須的,但並不是所有語言都有一個默認的截止時間。

RPC 終止

在 gRPC 裡,客戶端和服務端對調用成功的判斷是獨立的、本地的,他們的結論可能不一致。這意味著,比如你有一個 RPC 在服務端成功結束("我已經返回了所有應答!"),到那時在客戶端可能是失敗的("應答在最後期限後才來到!")。也可能在客戶端把所有請求發送完前,服務端卻判斷調用已經完成了。

取消 RPC

無論客戶端還是服務端均可以再任何時間取消一個 RPC 。一個取消會立即終止 RPC 這樣可以避免更多操作被執行。它不是一個"撤銷", 在取消前已經完成的不會被回滾。當然,通過同步調用的 RPC 不能被取消,因為直到 RPC 結束前,程序控制權還沒有交還給應用。

元數據集

元數據是一個特殊 RPC 調用對應的信息(授權詳情]) ,這些信息以鍵值對的形式存在,一般鍵的類型是字符串,值的類型一般也是字符串(當然也可以是二進制數據)。元數據對 gRPC 本事來說是不透明的 - 它讓客戶端提供調用相關的信息給服務端,反之亦然。

頻道

在創建客戶端存根時,一個 gRPC 頻道提供一個特定主機和端口服務端的連接。客戶端可以通過指定頻道參數來修改 gRPC 的默認行為,比如打開關閉消息壓縮。一個頻道具有狀態,包含已連接和空閒 。gRPC 如何處理關閉頻道是語言相關的。有些語言可允許詢問頻道狀態。

"


分享到:


相關文章: