gRPC 是什么
gRPC是goole開源的一個RPC框架和庫,支持多語言之間的通信。底層通信采用的是 HTTP2 協議。gRPC在設計上使用了 ProtoBuf 這種接口描述語言。這種IDL語言可以定義各種服務,google還提供了一種工具 protoc 來編譯這種IDL語言,生成各種各樣的語言來操作服務。
gPRC特點
- 定義服務簡單,可以很快的搭建出一個RPC調度的服務
- gRPC是與語言無關,平台無關的。你定義好了一個protobuf協議,就可以用protoc生成不同語言的協議框架
- 使用HTTP2協議,支持雙向流。客戶端和服務端可以雙向通信
gRPC為了解決什么問題
gRPC其實就是一種RPC,解決服務的遠程過程調用問題。
它使得我們遠程調用就像調用本地函數一樣,程序員無需關心交互的細節。
RPC與RESTful區別是什么
-
在客戶端和服務端通信還有一種基於http協議的 RESTful 架構模式,RESTful一般是對於資源的操作,它是名詞(資源地址),然后添加一些動作對這些資源進行操作。
而RPC是基於函數,它是動詞。 -
RPC一般基於TCP協議,當然gRPC是基於HTTP2,但它也是比HTTP協議更加有效率和更多特性。
RESTful一般都是基於HTTP協議 -
傳輸方面:自定義的TCP協議或者使用HTTP2協議,報文體積更小,所以傳輸效率更高
RESTful一般基於http協議,報文體積大 -
gRPC用的是protobuf的IDL語言,會編碼為二進制協議的數據,而RESTful一般是用json的數據格式,所以json格式的編解碼更耗時
為什么還是有很多公司用RESTful
以函數為基礎的模式(RPC),如果服務端添加了一個函數,那么客戶端也必須添加一個函數。
而以資源為操作基礎的RESTful,URI對應的服務變化了,客戶端一般是不需要關心和更新的,它對客戶端是透明的。
所以RPC的操作變更,有時比RESTful的復雜,因為RCP需要2邊都要添加代碼,也就增加了工作量。
並且json格式是可閱讀的格式,gRPC編碼后是二進制格式,對人不友好,不利於閱讀.
調試排錯RPC也比RESTful難,畢竟HTTP大家都很熟悉,而RPC協議一般是自定義協議,需要程序員自己去研究。
那怎么選擇呢?RPC OR RESTful
一般公司內部服務並發大,效率要求比較高的,可以用RPC。所以一般大公司內部用RPC比較多。不過大公司對外提供的api很多都是基於http的RESTful,為什么?因為這個簡單、易懂,大家都熟悉,使用就方便。
而業務量比較小,並發小,可以直接用RESTful,json,不管是公司內部服務間通信,還是對外提供api服務。
所以選擇:都是根據自己公司業務需求來判斷,適合使用哪種,就選擇哪種,不要盲目跟風,造成公司不必要的資源浪費。
golang中使用RESTful,用json傳輸數據,一般使用 https://github.com/gorilla/mux , https://github.com/gin-gonic/gin, https://github.com/labstack/echo,https://github.com/emicklei/go-restful 等
golang中的RPC現在一般使用g家的gRPC, https://grpc.io/, 畢竟大家都相信g家的技術實力 - -!
Protocol Buffers
這是google開源的並且非常成熟的用於數據結構序列化的框架。Protocol Buffers在github上的地址.
使用protocol來序列化數據,需要編寫一個proto文件,在proto文件中定義你的服務,rpc操作,返回和請求數據格式。
protocol buffers的數據是一個結構化的消息,每個消息都是一小的邏輯信息的記錄,消息中包含了一系列的鍵值對,稱之為屬性,一個簡單的例子:
message Person {
string name = 1;
int32 age = 2;
bool isPay = 3;
}
定義了你傳輸的數據結構,就可以用protoc
來生成對應語言的代碼。這些代碼提供了方法,可以操作每個屬性,可以將數據序列化為元數據傳輸給對方,也可以將對方發送過來的元數據進行解析。
例子:
// 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的客戶端和服務端代碼,和一般的protocol buffers代碼一樣,
可以構建,序列化,反序列化消息。
Protocol Buffer 官方文檔: https://developers.google.com/protocol-buffers/docs/overview
從這里也可以獲取 protoc 插件,從而生成你擅長語言的代碼。
gRPC的四種定義方式
gRPC允許用戶定義四種形式的rpc方法(原文參照:https://grpc.io/docs/guides/concepts.html):
A.客戶端發送請求到服務端,然后服務端給出一個響應,就像一個普通的方法定義一樣,如下所示:
rpc SayHello(HelloRequest) returns (HelloResponse) {};
B.服務端的流式rpc:客戶端發送一個請求到服務端,然后得到一個流用於讀取服務端的的消息,客戶端從返回的流中讀取所有的信息,如下所示:
rpc LotsOfReplies(HelloRequest) returns (stream HelloResponse) {};
C.客戶端流式rpc: 客戶端使用流將信息發送個服務端,只要客戶端發送完所有的信息給服務器,就開始等待服務端的響應,如下所示:
rpc LotsOfGreeting(stream HelloRequest) returns (HttpResponse) ;
D.雙向流式rpc:服務端與客戶端都是用讀寫流發送數據給對方。這兩個流式相互獨立的,所以他們的讀寫可以是任意順序的,例如:服務端在接受到客戶的所有的信息之前就已經開始響應,
也可以先讀取數據然后再寫數據,或者其他任何組合,如下所示:
rpc SayHello(stream HelloRequest) returns (HelloResponse) ;