gRPC 一定要使用 Protobuf 吗?

共 3930字,需浏览 8分钟

 ·

2020-09-10 20:44

点击上方蓝色“Go语言中文网”关注我们,领全套Go资料,每天学习 Go 语言

JSON payload 实现简易的请求和响应的内省。

介绍

大家经常说 gRPC 是基于 Google Protocol Buffers[1] payload 格式的,然而这不完全正确。gRPC payload 的默认格式是 Protobuf,但是 gRPC-Go 的实现中也对外暴露了 Codec interface[2] ,它支持任意的 payload 编码。我们可以使用任何一种格式,包括你自己定义的二进制格式、flatbuffers[3]、或者使用我们今天要讨论的 JSON ,作为请求和响应。

服务端准备

我已经基于 JSON payload 实现[4]grpc/encoding.Codec,创建了一个示例库[5]。服务端的准备工作仅仅像引入一个包那样简单;

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())),
    )
}

示例库代码包含有完整示例的客户端[6]

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[7] 加到 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[8] 上或 在 Gophers Slack jbrandhorst 下联系我。很高兴听到你的想法。


via: https://jbrandhorst.com/post/grpc-json/

作者:Johan Brandhorst[9]译者:lxbwolf[10]校对:polaris1119[11]

本文由 GCTT[12] 原创编译,Go 中文网[13] 荣誉推出

参考资料

[1]

Google Protocol Buffers: https://developers.google.com/protocol-buffers/

[2]

interface: https://godoc.org/google.golang.org/grpc/encoding#Codec

[3]

flatbuffers: https://grpc.io/blog/flatbuffers

[4]

实现: https://github.com/johanbrandhorst/grpc-json-example/blob/master/codec/json.go

[5]

一个示例库: https://github.com/johanbrandhorst/grpc-json-example

[6]

客户端: https://github.com/johanbrandhorst/grpc-json-example/blob/master/cmd/client/main.go

[7]

gRPC HTTP2 message payload header: https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md#requests

[8]

@johanbrandhorst: https://twitter.com/JohanBrandhorst

[9]

Johan Brandhorst: https://jbrandhorst.com/

[10]

lxbwolf: https://github.com/lxbwolf

[11]

polaris1119: https://github.com/polaris1119

[12]

GCTT: https://github.com/studygolang/GCTT

[13]

Go 中文网: https://studygolang.com/



推荐阅读


学习交流 Go 语言,扫码回复「进群」即可


站长 polarisxu

自己的原创文章

不限于 Go 技术

职场和创业经验


Go语言中文网

每天为你

分享 Go 知识

Go爱好者值得关注


浏览 131
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报