gRPC 預設使用 protocol buffers。
service HelloService { rpc SayHello (HelloRequest) returns (HelloResponse); } message HelloRequest { string greeting = 1; } message HelloResponse { string reply = 1; }
gRPC 可以定義四種型別服務:
Unary RPCs:一次請求,一次回覆。
rpc SayHello(HelloRequest) returns (HelloResponse);
伺服器端流式請求:使用者端傳送一次請求,伺服器端流式返回一系列資料。
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse);
使用者端流式請求:使用者端流式寫入一系列請求,然後傳送到伺服器端。使用者端寫完請求後,等待伺服器端接受並返回結果。
rpc LotsOfGreetings(stream HelloRequest) returns (HelloResponse);
雙向流式請求:使用者端和伺服器端雙向傳送資料流,各自獨立。可以隨讀隨寫,或者一次性讀完再寫。
rpc BidiHello(stream HelloRequest) returns (stream HelloResponse);
首先在 .proto 檔案中定義一個服務,然後使用 gRPC 提供的 pb 編譯外掛來生成使用者端和伺服器端程式碼。
同步 RPC 請求(傳送請求,阻塞直到伺服器端返回結果)和我們通常所說的 RPC 定義最為接近。但是,在實際應用中,非阻塞非同步請求更適合。
使用者端傳送一次請求,獲取一次返回。
伺服器端返回的是一個資料流。在伺服器端傳送完業務資料後,會繼續返回狀態資訊。
使用者端傳送的是一個請求資料流。
使用者端和伺服器端雙向傳送資料流,各自獨立。可以隨讀隨寫,或者一次性讀完再寫。
gRPC 允許使用者端宣告超時(請求 DEADLINE_EXCEEDED 異常之前等待的時間)。伺服器端可以通過此來判定請求是否超時及剩餘處理時間。
gRPC 中使用者端和伺服器端都可以獨立終止請求。比如伺服器端已經成功響應請求,但是使用者端超時終止;伺服器端在接收完使用者端請求資料前限頻校驗終止請求流程。
使用者端和伺服器端都可以在任何時候取消 RPC 流程。
RPC 請求後設資料,kv 列表形式,key 為 string 型別,value 通常為string,也可以為二進位制。
key 大小寫敏感,不能以 grpc- 做字首(保留),二進位制 value 的 key 以 -bin 結尾。
gRPC 不會使用使用者自定義的後設資料。
後設資料使用,不同開發語言可能不同。
gRPC channel 是使用者端到伺服器端的連結。用以建立使用者端 stub。
channel 提供相應的引數設定控制 gRPC 請求行為,例如互動資料壓縮等。
channel 的狀態包括已建立連結及空閒。
rpc 請求初始化包括:使用者端負載均衡,傳輸層 HTTP/2 請求建立及請求伺服器端相應的業務介面。
儘量重用 stubs 和 channels。
2、提供心跳機制以確保 HTTP/2 連線即使在系統業務不活躍時段仍能保持活躍,避免因 RPC 請求初始化導致的響應延遲。
3、對於可能存續長時間的資料流請求互動,適宜使用流式處理,避免頻繁的 RPC 初始化。但是流式處理也存在無法動態均衡負載的及debug 困難的問題。雖然可以在小規模請求上提升效能,但是會因為負載均衡因素及複雜性降低整體擴充套件性。(python 除外)
4、每一個 gRPC channel 可以使用 0 個或多個 HTTP/2 連結,每個連結可以承載一定數量的的並行資料流。當連結上活躍的 RPC 請求達到上限,新進的請求會進入呼叫端等待佇列。因此,對於高負載或持久的流式請求會因此產生效能問題。對於此,可以使用如下兩種方式處理:
5、對於 Java 語言
使用非阻塞 stubs 來並行處理 RPC 請求。
提供自定義連線池,根據實際的業務負載來設定相關引數。