关于 grpc, proto 的疑惑

2023-12-20 18:43:48 +08:00
 CyouYamato

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

message Person { string params = 1; }

2408 次点击
所在节点    程序员
20 条回复
dayeye2006199
2023-12-20 18:52:21 +08:00
因为鬼知道 params 里有什么
helone
2023-12-20 18:54:16 +08:00
一个是传输层面,你直接一个参数肯定会显著增加数据包大小,第二个就是 json encode decode 其实也需要时间,本身 grpc proto 定义各种参数就是为了减少这种耗时
XCFOX
2023-12-20 18:57:36 +08:00
Protocol Buffers 是强类型的,能让通讯双方明确数据结构和类型,proto 文件本身具有文档的功能。
json 只是单纯的无类型数据,按 message Person { string params = 1; } 这么写过两个礼拜你自己都不知道 params 里有什么。
willchen
2023-12-20 19:05:36 +08:00
短小精悍
Kaisar
2023-12-20 19:10:00 +08:00
照这么说直接传 json 不就完了
XCFOX
2023-12-20 19:21:28 +08:00
借楼吐槽一下 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
2023-12-20 19:29:28 +08:00
就是要去掉 JSON 的 key 你还想把它塞进去 怎么想的
BingGan
2023-12-20 19:40:13 +08:00
这个问题就是在问 protobuf 和 json 的区别嘛,随便一搜就有。

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

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

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

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

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

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