关于 grpc, proto 的疑惑

334 天前
 CyouYamato

好奇为什么 proto 文件需要定义各种参数?直接参数类型为 string 值为 json 不可以吗? message Person { string name = 1; int32 age = 2; }

message Person { string params = 1; }

2356 次点击
所在节点    程序员
20 条回复
dayeye2006199
334 天前
因为鬼知道 params 里有什么
helone
334 天前
一个是传输层面,你直接一个参数肯定会显著增加数据包大小,第二个就是 json encode decode 其实也需要时间,本身 grpc proto 定义各种参数就是为了减少这种耗时
XCFOX
334 天前
Protocol Buffers 是强类型的,能让通讯双方明确数据结构和类型,proto 文件本身具有文档的功能。
json 只是单纯的无类型数据,按 message Person { string params = 1; } 这么写过两个礼拜你自己都不知道 params 里有什么。
willchen
334 天前
短小精悍
Kaisar
334 天前
照这么说直接传 json 不就完了
XCFOX
334 天前
借楼吐槽一下 gRPC ,用着是真的麻烦:
1. 每次新加函数都要编写 .proto 文件,再重新代码生成;
2. protobuf 语法也很繁琐,在语言里序列号反序列化也麻烦;
3. 没有内置的负载均衡方案,需要另外实现或者网络配置;

马上 2024 年了,推荐使用 NATS 作为远程调用的方案:
✅使用 json ,简单高效
✅云原生、轻松水平扩展、高性能,服务与 NATS 之间始终保持连接,省去了反复建立 TCP 连接的开销
✅内置负载均衡、服务发现
✅可选的消息队列、键值存储

https://nats.io/
https://github.com/nats-io/nats.go/blob/main/micro/README.md
silentsky
334 天前
就是要去掉 JSON 的 key 你还想把它塞进去 怎么想的
BingGan
334 天前
这个问题就是在问 protobuf 和 json 的区别嘛,随便一搜就有。

头一个缺点是非字符串的编码低效。比如 int 字段的值是 12345 ,内存表示只占两个字节,转成 JSON 却要五个字节。bool 字段则占了四或五个字节。

再一个缺点就是信息冗余。同一个接口同一个对像,只是 int 字段的值不同,每次都还要传输”int”这个字段名。

等等,这是缺点吗?是!可 JSON 为什么会有这些毛病呢?因为 JSON 在可读性和编码效率之间选择了可读性,所以效率方面做了一定的牺牲。

好了,现在人们觉得效率是主要矛盾了,那就必然会牺牲可读性。为此,Protobuf 一方面选用了 VarInts 对数字进行编码,解决了效率问题;另一方面给每个字段指定一个整数编号,传输的时候只传字段编号,解决了冗余问题。更多细节可参考的另一篇文章

在传输的时候只传了字段编号固然可以提高传输效率,但接收方如何知道各个编号对应哪个字段呢?只能事先约定了。就像当年地下工作者一样,一人拿一个密码本。Protobuf 使用 .proto 文件当密码本,记录字段和编号的对应关系
gzlock
334 天前
protobuf 挺好用的啊,我在自己的二进制文件格式里用上了 protobuf

https://github.com/whimsy-ai/ilp_file_codec#the-ilp-file-structure
cloudzhou
334 天前
@XCFOX 你提的这些问题,在一个成熟框架里面,业务开发根本不需要关注
mason961125
334 天前
@XCFOX 推广请去推广区域,不要污染正常讨论。
SilentRhythm
334 天前
protobuf 对比 json ,在传输层解决的是传递内容大小的问题,进而提高传输效率。
假如你 json 有一个 key 命名长度 50 ,还是个 20 长度数组,那你使用 protobuf 就节省了接近 1000 个字符的传输量了。
iOCZS
334 天前
有了 proto 文件,可以省下 key 的代价,只要发送序号就行。编码方式其实就那些,还想继续扣消耗,那就查表喽。这种思想都是相通的,包括 http2 的请求头压缩,也是类似的查表。
oswinw
334 天前
没指令集的时候,prorobuf 和 json 序列化反序列化开销都挺大的
oswinw
334 天前
@oswinw 说错了,是效率差异很大
deorth
334 天前
那你用 jsonrpc 不就完了
beneo
334 天前
gRPC 是想着法子在网卡打满的情况下支持更多请求,和你的追求有点不一样
CyouYamato
334 天前
感谢,大佬们的回复。
我用的是 ts ,因为 proto3 不支持 optional repeated,而生成工具这边用的是:ts-proto 。生成后的代码要么全是可选,要么就是自己手动指定的可选,或者再加上 message 可选(也不支持可选数组)。而且 proto 作者明确表示不会考虑支持 optional repeated ,非常疑惑。
为何不用 http ,是组长测试线上 http 维持连接只能在一分钟左右,而 grpc 可以很久。我们业务需要维持很长时间的远程调用。个人觉得 http 和 grpc 底层都是 tcp,应该也能维持很久。
changz
334 天前
纠正一下 protobuf 在 3.15 后是支持 optional 的
julyclyde
322 天前
@CyouYamato http 是由双方其中之一主动掐断 tcp 的

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1002059

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX