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

求教各位后端大佬,用 gRPC 来实现 TS 与 Python 服务之间的通信时遇到了问题

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

    目的

    实现后端微服务架构中 TS 与 Python 服务之间的通信,希望能通过维护同一套类型定义/ Schema 保证 single source of truth ,提高接口可维护性。

    尝试过的方案

    1. 最简单的方案,Python 服务用 Flask 实现普通的 REST API 来对其他模块提供服务。问题是一方接口定义更改时,另一方需要同步更改,如果是纯 TS 项目的话,得益于类型信息共享,先改类型定义,所有受影响的地方都能及时发现,后改相关代码就很方便,也比较安心,但如果是多语言的话做不到这点
    2. 借此机会想试试 RPC 替代 REST ,于是尝试了一下 gRPC ,本身多语言支持,还有通用统一的 Protobuf ,看上去很美好,然而可能是我太菜不熟悉,感觉这玩意用起来槽点太多了……

    使用 gRPC 时遇到的问题

    1. 首先最让我感到意外的一点是,那么多官方支持的语言里面,居然没有 JS (还是在连 Dart 和 Ruby 都有的情况下)。虽然有个 grpc/grpc-node,但对 JS 生态的支持看上去不是特别理想
    2. Protobuf 生成的代码质量一言难尽:
      1. 在 TS 项目中,想按照官方文档里的例子那样使用 @grpc/grpc-js 的话,需要自动生成类型定义。找了一圈,发现只有 @grpc/proto-loader 自带的 proto-loader-gen-types 生成的还算可用,然而还是有坑,比如引入路径中没有文件扩展名,而在 TS 中使用 ESM + module": "node16" 时文件扩展名是强制的,所以还是需要手动修改生成的代码。另外有个 @bufbuild/protobuf,号称是唯一一个全部通过 Protobuf 兼容性测试的,结果生成的东西 @grpc/grpc-js 压根用不了,只能用他们的配套库 @connectrpc/connect,说是兼容 gRPC ,也只是客户端部分可以发起 gRPC 而已

      2. protoc 生成的 Python 代码也有引入路径问题,如果文件不在根目录下,就会报错找不到模块,于是你还是需要手动修改自动生成的代码

      3. 官方文档太差了,没有更多用例来解释真实场景里是什么样的,比如服务端的部分:

        server.add_insecure_port("[::]:" + PORT)
        
        server.bindAsync(
            `0.0.0.0:${PORT}`,
            gRPC.ServerCredentials.createInsecure(),
            (err, port) => {},
        );
        

        这都 insecure 了,那生产环境中想 secure 该怎么办?

    上面的问题 GitHub 也有相关 Issue 讨论,但到目前为止似乎都不了了之了。想问一下有相关经验的佬们:

    1. 我这个需求用 gRPC 是否合适?除此之外还有其他解决方案吗?
    2. 在 TS 和 Python 下,正确的使用姿势分别是什么?除了裸用官方的库 @grpc/grpc-js/grpcio之外,还有其他基于 gRPC 的更好用的框架吗?
    21 条回复    2025-02-28 15:12:28 +08:00
    chesha1
        1
    chesha1  
       32 天前
    用 openapi ,然后生成 ts/python 客户端代码?感觉使用应该简单一点(@hey-api/openapi-ts 和 openapi-python-client ),方案比 grpc 简单点,都是 restful api ,不过性能肯定是比不了了
    doublespout
        2
    doublespout  
       32 天前
    @chesha1 这个方案靠谱,jsonschema 库还是稳定的
    julyclyde
        3
    julyclyde  
       32 天前
    用 protobuf 也依然需要另一端同步修改吧
    难道你不用给 proto 文件就可以直接用?
    jworg
        4
    jworg  
       32 天前
    @grpc/grpc-js 我记得是动态 hook proto 文件,类型检查的很好,什么时候退化了吗。gRPC.ServerCredentials.createInsecure() 这一句只是指 grpc 的 tcp 是裸传输的,能中间抓包然后 proto 反解到传输的是什么。要加 tls ,得使用 grpc.ServerCredentials.createSsl() 的方法。
    jworg
        5
    jworg  
       32 天前   ❤️ 1
    从楼主的整个思路来看,还是 rest api 吧,整个查资料的深度不足以应付后面的 grpc 相关的更大的坑。
    nomagick
        6
    nomagick  
       32 天前
    什么是 gRPC, 就是说 Google RPC, 咱要不是能和 Google 比划比划的话,还是老老实实 HTTP 吧
    jworg
        7
    jworg  
       32 天前
    python 的那个导入问题,翻了翻书签,应该和这个 issue 有关系 https://github.com/protocolbuffers/protobuf/issues/1491 用 google 的东西,你得顺从 google 那一套,并且勤翻 issue 区和源码。
    TJT
        8
    TJT  
       32 天前
    用 ts-proto 更好,我们已经大范围使用了
    Maboroshii
        9
    Maboroshii  
       32 天前
    grpc 太复杂了,依赖库版本和 protoc 也一直更新,保不齐哪天就不兼容了,生成出来的代码每次 diff 一大片也挺难受的(我这边是 golang 用的,改旧项目的 grpc 简直爆炸,根本就一点都不想维护)。 简单的远程调用,我感觉还是用 http 吧,想提升性能可以用 http2 ?毕竟 grpc 也是基于 http2 的
    Maboroshii
        10
    Maboroshii  
       32 天前
    顺带 protobuf 最大优势也就是性能上,多项目、多人维护的时候,工作流程上也是脑袋都大了。
    cj323
        11
    cj323  
       32 天前 via iPhone
    不好用是因为没有人用 TS/python 搭配 grpc 。gprc 主要就是提升传输效率,但你传输层提升半天最后应用层进 node/v8 这种运行时又会变很慢。就像开 F1 下午五点去东三环一样,意义微乎其微。
    Vegetable
        12
    Vegetable  
       32 天前
    grpc 的易用性从来就没好过吧,用它团队里总得有几个人头疼。

    其实 jsonschema 在两边都能找到可用的生成器,我觉得好于 grpc
    minami
        13
    minami  
       32 天前
    1 、protobuf 本身就很糟糕,如果你不是谷歌那种全公司代码在一个仓库里的管理方式,建议别用
    2 、绝大部分的 RPC 需求用 JSON-RPC 就能满足,性能瓶颈根本不在 RPC 库上
    xuanbg
        14
    xuanbg  
       32 天前
    你一边接口的参数/返回数据的结构变了,用什么 rpc 协议都不能让你不用改调用者的逻辑就能实现同步啊。
    superhot
        15
    superhot  
    OP
       32 天前
    感谢各位的解答,我再去看看 json schema
    renyijiu
        16
    renyijiu  
       32 天前
    用 connectrpc 支持 grpc, buf 算是 proto 这块很好用的工具了, https://buf.build/explore
    superhot
        17
    superhot  
    OP
       32 天前
    @renyijiu 这个我也看了,好像只支持 TS 做客户端发 gPRC 请求,做不了服务端?如此的话 Python 那块还是没法解决
    renyijiu
        18
    renyijiu  
       32 天前
    @superhot #17 https://connectrpc.com/docs/node/getting-started node 版本不是可以作为 server 吗?当然我对 js 很了解
    yzld2002
        19
    yzld2002  
       32 天前
    一样的用法,看了下我 ts 这边用的是 grpc_tools_node_protoc_plugin ,生成的代码没动过就可以带 type
    反倒是 python 这边生成的代码过不了 lint ,而且 import 确实有问题,得自己手改一下
    HappyAndSmile
        20
    HappyAndSmile  
       31 天前
    不是吧,不理解楼上的人的说法,即使 protobuf ,gRPC 不好用,也总能用吧,不至于用不到吧?另外,每次改动后,生成一大片 diff? 是有 diff ,也没多大啊
    iflint
        21
    iflint  
       31 天前
    ts 里面用 GRPC 确实比较难受。之前做出过 ts 服务端和 Android (kt) 客户端的通信,kt 里面有明确的接入步骤和官方的插件生成产物。ts 的话也有不少插件但是能很舒服用的不多。目前在用的是 grpc_tools_node_protoc_ts 、ts-proto 、ts-protoc-gen 这几个。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3931 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 04:11 · PVG 12:11 · LAX 21:11 · JFK 00:11
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.