gRPC 和通常的基於TCP的實現不同,是直接基於HTTP2 協議的。HTTP2 使得grpc 能夠更好的適用於移動客戶端和服務端通信的使用場景,並且連接多路復用也保證了RPC 的效率。
gRPC 的協議設計上很好的使用了HTTP2 現有的語義,請求和響應的數據使用HTTP Body 發送,其他的控制信息則用Header 表示。先看個例子,假設Protobuf 定義如下:
package foo.bar; message HelloRequest { string greeting = 1; } message HelloResponse { string reply = 1; } service HelloService { rpc SayHello(HelloRequest) returns (HelloResponse); }
在這裡面我們定義了一個service HelloService。grpc 為這樣一個調用發送的請求為:
HEADERS (flags = END_HEADERS) :method = POST :scheme = http :path = /foo.bar.HelloService/SayHello :authority = api.test.com grpc-timeout = 1S content-type = application/grpc+proto grpc-encoding = gzip authorization = Bearer y235.wef315yfh138vh31hv93hv8h3v DATA (flags = END_STREAM) <Delimited Message>
Http 請求的Path 部分用來表示調用哪個服務,格式是/{package}.{ServiceName}/{RpcMethodName},content-type 目前取值都是application/grpc+proto,將來grpc 支持除Protobuf 之外的協議如Json 時,會有別的值。grpc-encoding 可以有gzip, deflate, snappy 等取值,表示采用的壓縮方法。grpc-timeout 表示調用的超時時間,單位有Hour(H), Minute(M), Second(S), Millisecond(m), Microsecond(u), Nanosecond(n) 等。
除了grpc 定義的標准頭之外,也可以自己添加新的頭。如果是二進制的Header,則Header Name 以-bin 結尾,Header Value 是經過Base64 編碼的二進制數據。
服務端對這個請求返回一個Response:
HEADERS (flags = END_HEADERS) :status = 200 grpc-encoding = gzip DATA <Delimited Message> HEADERS (flags = END_STREAM, END_HEADERS) grpc-status = 0 # OK trace-proto-bin = jher831yy13JHy3hcgrpc-status 為0 表示請求沒有出現問題,成功返回。
grpc 還定義了GOAWAY Frame, 當Server 斷開一個連接的時候,需要向客戶端發送這樣一條消息;以及PING Frame,接受到PING Frame 後直接原樣返回數據,用於連接存活檢測和延遲檢測。
HTTP2 的Header 並不是特別高效的格式,存儲上和解析上都有一些效率問題。如果啟用加密連接的話,則會有更多的效率開銷。