JSON payload 實現簡易的請求和響應的內省。
介紹
大家經常說 gRPC 是基於 Google Protocol Buffers payload 格式的,然而這不完全正確。gRPC payload 的預設格式是 Protobuf,但是 gRPC-Go 的實現中也對外暴露了 Codec
interface ,它支援任意的 payload 編碼。我們可以使用任何一種格式,包括你自己定義的二進位制格式、flatbuffers、或者使用我們今天要討論的 JSON ,作為請求和響應。
服務端準備
我已經基於 JSON payload 實現 了 grpc/encoding.Codec
,建立了一個示例庫。服務端的準備工作僅僅像引入一個包那樣簡單;
import _ "github.com/johanbrandhorst/grpc-json-example/codec"
這行程式碼註冊了一個基於 json
內容的子型別 JSON Codec
,我們在後面會看到這對於方便記憶很重要。
Request 示例
gRPC 客戶端
使用 gRPC 客戶端,你只需要使用合適的內容子型別作為 grpc.DialOption
來初始化:
import "github.com/johanbrandhorst/grpc-json-example/codec"
func main() {
conn := grpc.Dial("localhost:1000",
grpc.WithDefaultCallOptions(grpc.CallContentSubtype(codec.JSON{}.Name())),
)
}
示例庫程式碼包含有完整示例的客戶端。
cURL
更有趣的是,現在我們可以用 cURL 寫出請求(和讀取響應)!請求示例:
$ Echo -en '\x00\x00\x00\x00\x17{"id":1,"role":"ADMIN"}' | curl -ss -k --http2 \
-H "Content-Type: application/grpc+json" \
-H "TE:trailers" \
--data-binary @- \
https://localhost:10000/example.UserService/AddUser | od -bc
0000000 000 000 000 000 002 173 175
\0 \0 \0 \0 002 { }
0000007
$ Echo -en '\x00\x00\x00\x00\x17{"id":2,"role":"GUEST"}' | curl -ss -k --http2 \
-H "Content-Type: application/grpc+json" \
-H "TE:trailers" \
--data-binary @- \
https://localhost:10000/example.UserService/AddUser | od -bc
0000000 000 000 000 000 002 173 175
\0 \0 \0 \0 002 { }
0000007
$ Echo -en '\x00\x00\x00\x00\x02{}' | curl -k --http2 \
-H "Content-Type: application/grpc+json" \
-H "TE:trailers" \
--data-binary @- \
--output - \
https://localhost:10000/example.UserService/ListUsers
F{"id":1,"role":"ADMIN","create_date":"2018-07-21T20:18:21.961080119Z"}F{"id":2,"role":"GUEST","create_date":"2018-07-21T20:18:29.225624852Z"}
解釋
使用 cURL
傳送請求需要手動把 gRPC HTTP2 message payload header 加到 payload:
'\x00\x00\x00\x00\x17{"id":1,"role":"ADMIN"}'
#<-->----------------------------------------- Compression boolean (1 byte)
# <-------------->------------------------- Payload size (4 bytes)
# <--------------------->-- JSON payload
請求頭必須包含 TE
和正確的 Content-Type
:
-H "Content-Type: application/grpc+json" -H "TE:trailers"
在 Content-Type
頭中 application/grpc+
後的字串需要與服務端註冊的 codec 的 Name()
相吻合。這就是內容子類.
endpoint 需要與 proto 包的名字、服務和方法三者的名字都匹配:
https://localhost:10000/example.UserService/AddUser
響應頭與請求頭一致:
'\0 \0 \0 \0 002 { }'
#<-->------------------------ Compression boolean (1 byte)
# <------------>---------- Payload size (4 bytes)
# <--->-- JSON payload
總結
我們已經展示了我們可以輕易地在 gRPC 中使用 JSON payload,甚至可以用 JSON payload 直接傳送 cURL 請求到我們的 gRPC 服務,沒有代理,沒有 grpc 閘道器,除了引入一個必要的包也沒有其他的準備工作。
如果你對本文感興趣,或者有任何問題和想法,請在 @johanbrandhorst 上或 在 Gophers Slack jbrandhorst
下聯絡我。很高興聽到你的想法。
via: https://jbrandhorst.com/post/grpc-json/
作者:Johan Brandhorst 譯者:lxbwolf 校對:polaris1119