gRPC是Google開發的高性能、通用的開源RPC框架,其由Google主要面向移動應用開發並基於HTTP/2協議標準而設計,基於Protobuf(Protocol Buffers)序列化協議開發,且支持衆多開發語言。在gRPC中一個客戶端能夠像使用本地對象那樣直接調用位於不一樣機器上的服務端應用的方法(methods)。這讓你可以更容易的構建分佈式的應用和服務。和其餘RPC
系統相似,gRPC
也是基於定義一個服務,指定服務能夠被遠程調用的方法以及他們的參數和返回類型。在服務端,實現服務的接口而後運行一個gRPC
服務來處理可出端的請求。在客戶端,客戶端擁有一個存根(stub在某些語言中僅稱爲客戶端),提供與服務器相同的方法。編程
·gRPC
客戶端和服務器能夠在各類環境中運行並相互通訊,而且可使用gRPC
支持的任何語言編寫。所以,例如,您可使用Go,Python或Ruby的客戶端輕鬆地用Java建立gRPC
服務器。此外,最新的Google API的接口將擁有gRPC
版本,可以讓您輕鬆地在應用程序中內置Google功能。服務器
默認狀況下,gRPC使用protocol buffer,用於序列化結構化數據(儘管它能夠與其餘數據格式(例如JSON)一塊兒使用)。使用協議緩衝區的第一步是在proto文件中爲要序列化的數據定義結構:proto文件擴展名爲.proto的普通文本文件。protocol buffer數據被構造爲消息,其中每一個消息都是信息的邏輯記錄,其中包含一系列稱爲字段的名稱/值對。這是一個簡單的示例:網絡
message Person { string name = 1; int32 id = 2; bool has_ponycopter = 3; }
定義了數據結構後,就可使用protocol buffer編譯器protoc
生成你所選語言的數據訪問類。訪問類爲每一個字段提供了簡單的訪問器(例如name()
)和set_name()
),以及將整個結構序列化爲原始字節或從原始字節中解析出整個結構的方法-例如,若是您選擇的語言是C ++,則在上面的示例將生成一個名爲Person
的類。而後,您能夠在應用程序中使用此類來填充,序列化和檢索Person
的protocol buffer消息。數據結構
除此以外你還要在.proto
件中定義gRPC服務,並將RPC方法參數和返回類型指定爲protocol buffer消息:框架
// The greeter service definition. service Greeter { // Sends a greeting rpc SayHello (HelloRequest) returns (HelloReply) {} } // The request message containing the user's name. message HelloRequest { string name = 1; } // The response message containing the greetings message HelloReply { string message = 1; }
gRPC使用也是使用編譯器protoc
從proto文件生成代碼,不過編譯器要首先安裝一個gRPC插件。使用gRPC插件,你能夠得到生成的gRPC客戶端和服務器代碼,以及用於填充,序列化和檢索消息類型的常規protocol buffer訪問類代碼。異步
下面會更詳細地介紹gRPC裏的一些關鍵的概念。編程語言
與許多RPC系統同樣,gRPC圍繞定義服務的思想,指定可經過其參數和返回類型遠程調用的方法。默認狀況下,gRPC使用protocol buffer做爲接口定義語言(IDL)來描述服務接口和有效負載消息的結構。若是須要,可使用其餘替代方法。分佈式
service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string greeting = 1; } message HelloResponse { string reply = 1; }
gRPC容許定義四種服務方法:函數
rpc SayHello(HelloRequest) returns (HelloResponse){ }
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse){ }
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse) { }
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse){ }
在下面的RPC生命週期章節咱們會更詳細的比較這幾種不一樣的RPC。性能
從.proto
文件中的服務定義開始,gRPC提供了protocol buffer編譯器插件,插件可生成客戶端和服務器端代碼。 gRPC用戶一般在客戶端調用這些API,並在服務器端實現相應的API。
同步RPC調用會阻塞當前線程直到服務器收到響應爲止,這是最接近RPC所追求的過程調用抽象的近似方法。另外一方面,網絡本質上是異步的,而且在許多狀況下可以啓動RPC而不阻塞當前線程頗有用。
大多數語言中的gRPC編程界面都有同步和異步兩種形式。能夠在每種語言的教程和參考文檔中找到更多信息。
如今讓咱們具體看一下當一個gRPC客戶端調用了一個gRPC服務器的方法後都發生了什麼。咱們不會查看具體實現細節,留到後面的編程語言教程中再看實現細節。
首先來看一個最簡單的RPC類型,客戶端發送一個請求而後接受一個響應。
一個服務器流式RPC與簡單的一元RPC相似,不一樣的是服務器在接收到客戶端的請求消息後會發回一個響應流。在發送回全部的響應後,服務器的狀態詳情(狀態碼和可選的狀態信息)和可選的尾隨元數據會被髮回以完成服務端的工做。客戶端在接收到全部的服務器響應後即完成操做。
客戶端流式RPC也相似於一元PRC,不一樣之處在於客戶端向服務器發送請求流而不是單個請求。服務器一般在收到客戶端的全部請求後(但不必定)發送單個響應,以及其狀態詳細信息和可選的尾隨元數據。
在雙向流式RPC中,調用再次由客戶端調用方法發起,服務器接收客戶端元數據,方法名稱和期限。一樣,服務器能夠選擇發回其初始元數據,或等待客戶端開始發送請求。
接下來發生的狀況取決於應用程序,由於客戶端和服務器能夠按任何順序進行讀取和寫入-流操做徹底是獨立地運行。所以,例如,服務器能夠等到收到全部客戶端的消息後再寫響應,或者服務器和客戶端能夠玩「乒乓」:服務器收到請求,而後發回響應,而後客戶端發送基於響應的另外一個請求,依此類推。
gRPC容許客戶端指定在RPC被DEADLINE_EXCEEDED
錯誤終結前願意等待多長時間來讓RPC完成工做。在服務器端,服務器能夠查看一個特定的RPC是否超時或者還有多長時間剩餘來完成RPC。
如何指按期限或超時的方式因語言而異-例如,並不是全部語言都有默認期限,某些語言API按照期限(固定的時間點)工做,而某些語言API根據超時來工做(持續時間)。
在gRPC中,客戶端和服務端對調用是否成功作出獨立的基於本地的決定,並且兩端的結論有可能不匹配。這意味着,好比說,你可能會有一個在服務端成功完成(「我已經發送完全部響應了」)可是在客戶端失敗(「響應是在我指定的deadline以後到達的」)的RPC。服務器也有可能在客戶端發送全部請求以前決定RPC完成了。
客戶端或服務器均可以隨時取消RPC。取消操做將當即終止RPC,所以再也不進行任何工做。這不是「撤消」:取消以前所作的更改不會回滾。
元數據是以鍵值對列表形式提供的關於特定RPC調用的信息(好比說身份驗證詳情),其中鍵是字符串,值一般來講是字符串(可是也能夠是二進制數據)。元數據對gRPC自己是不透明的-它容許客戶端向服務器提供與調用相關的信息,反之亦然。
對元數據的訪問取決於語言。
一個gRPC通道提供了一個到指定主機和端口號的gRPC服務器的鏈接,它在建立客戶端存根(或者對某些語言來講就是「客戶端」)時被使用。客戶端能夠指定通道參數來更改gRPC的默認行爲,好比說打開/關閉消息壓縮。每一個通道都有狀態,狀態包括connected
和idle
(閒置)
gRPC怎麼處理關掉的通道是語言相關的,有些語言還容許查詢通道的狀態。