V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
CyouYamato
V2EX  ›  程序员

关于 grpc, proto 的疑惑

  •  
  •   CyouYamato · 364 天前 · 2403 次点击
    这是一个创建于 364 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    message Person { string params = 1; }

    20 条回复    2024-01-01 21:40:37 +08:00
    dayeye2006199
        1
    dayeye2006199  
       364 天前 via Android   ❤️ 1
    因为鬼知道 params 里有什么
    helone
        2
    helone  
       364 天前   ❤️ 1
    一个是传输层面,你直接一个参数肯定会显著增加数据包大小,第二个就是 json encode decode 其实也需要时间,本身 grpc proto 定义各种参数就是为了减少这种耗时
    XCFOX
        3
    XCFOX  
       364 天前   ❤️ 1
    Protocol Buffers 是强类型的,能让通讯双方明确数据结构和类型,proto 文件本身具有文档的功能。
    json 只是单纯的无类型数据,按 message Person { string params = 1; } 这么写过两个礼拜你自己都不知道 params 里有什么。
    willchen
        4
    willchen  
       364 天前
    短小精悍
    Kaisar
        5
    Kaisar  
       364 天前   ❤️ 2
    照这么说直接传 json 不就完了
    XCFOX
        6
    XCFOX  
       364 天前
    借楼吐槽一下 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
        7
    silentsky  
       364 天前 via Android
    就是要去掉 JSON 的 key 你还想把它塞进去 怎么想的
    BingGan
        8
    BingGan  
       364 天前 via iPhone   ❤️ 1
    这个问题就是在问 protobuf 和 json 的区别嘛,随便一搜就有。

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

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

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

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

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

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