字节的go框架为啥要支持thrift

197 阅读5分钟

最近发现字节跳动的go框架hertz中,同时支持 Thrift 和 Protobuf,这就很好奇,为啥还要支持Thrift?直接使用Protobuf不香吗?字节跳动这么大的公司,为什么要容忍两套协议共存的“复杂性”?

不仅增加的学习的难度,也增加了项目的复杂度,直接一套Protobuf不好嘛。

下面来看下Thrift 和 Protobuf的区别是什么?有什么区别和联系。

一、Thrift 和 Protobuf 到底是什么?

先来打个比方:

  • Thrift 更像是“包办婚姻”:你只要写好一份接口定义,它就自动帮你生成服务端、客户端代码,甚至连传输协议和序列化格式都一手包办。你说你要服务A调用服务B?没问题,全都安排上。

  • Protobuf 更像是“自由恋爱”:它本质上是一个数据序列化工具,你定义好数据结构,它帮你压缩得又小又快,但怎么传、怎么收,得你自己决定。这也带来了更多的灵活性。

🧩 技术特点快速对比

特性ThriftProtobuf
定位全家桶:RPC 框架 + 序列化 + 协议轻量级:数据结构定义 + 高效序列化
是否内置 RPC✅ 内置 RPC 支持❌ 需配合 gRPC 使用
生态成熟但偏老派新兴主流,广泛用于云原生体系
语言支持丰富更丰富,且官方维护更活跃
文件大小编码效率高,较紧凑通常更小,速度也更快

二、字节跳动为什么用了两者?——“历史的包袱 vs 新时代的选择”

字节跳动的微服务体系从一开始就是超大规模起步,核心服务早年很多都是基于 Thrift 构建的:

1. 早期:Thrift 是最佳实践

  • 内部通信多为服务间调用,Thrift 一站式支持 RPC、IDL(接口描述语言)、序列化、传输协议,降低了开发门槛。
  • 跨语言调用场景非常多(Java、Go、Python、C++ 并存),Thrift 提供统一协议,方便团队协作。
  • 服务数量爆发增长时,需要自动化代码生成和服务治理,Thrift 提供良好支撑。

一句话总结:早期上量快、架构要稳、Thrift 刚好能兜住一切


2. 中期转型:新项目开始拥抱 Protobuf + gRPC

随着架构逐步升级,字节也面临几个问题:

  • Thrift 的二进制协议虽高效,但封闭、文档少,不利于对外开放接口或异构系统集成
  • Protobuf/gRPC 成为云原生世界事实标准,k8s、Istio、Envoy、Linkerd 等组件都天然支持;
  • Protobuf 的序列化效率更高,配合 gRPC 性能极好,更适合做对延迟敏感或大数据量场景

因此,新服务、新业务逐渐迁向 Protobuf 是必然选择。尤其是在 Go 语言体系中,gRPC 本身在社区活跃,接入体验远胜 Thrift。


三、为什么两种都保留?并不是“拖延”,而是“工程智慧”

你可能会问:

“那为什么不彻底迁到 Protobuf?彻底统一岂不更好?”

理想是很美好,但现实是:

🧱 1. 系统庞大,Thrift 无法一夜弃用

  • 很多老服务年久失修,直接迁移成本高,涉及大量重构;
  • 一些依赖深度封装的工具链(比如自动化治理平台、服务注册发现)和 Thrift 高度绑定。

贸然替换,不但得不到性能收益,还可能带来灾难性的风险。


🔁 2. 字节的 Go 框架做了“协议抽象”处理

字节内部的微服务框架并不是直接写死 Thrift 或 Protobuf,而是做了统一封装层

  • 对开发者来说,只需要关注 service/handler 的逻辑,不关心底层协议;
  • 协议部分是“可插拔”的,框架根据配置选择使用 Thrift 或 Protobuf;
  • 老服务继续跑在 Thrift,新服务启动时指定 Protobuf 接入即可。

这种“协议无关”的设计极大减少了双协议共存的痛苦。


🧠 3. 多协议并存 ≠ 混乱,而是“按需选择工具”

  • 如果你写的是服务间 RPC,接口清晰、数据结构稳定,Thrift 更方便
  • 如果你要做对外接口、需要走网关、压缩数据包、接入云原生环境,Protobuf 更合适
  • 如果你要写异构系统对接、前后端交互、甚至移动端接入,Protobuf 几乎是唯一选择

四、工程上的最佳实践是什么?

最后,总结一下字节跳动在“多协议共存”方面的几个工程实践建议:

✅ 框架层封装好协议适配

把协议选型变成配置项,不让开发者关注底层细节。

✅ 老系统稳定运行,谨慎迁移

避免“为迁移而迁移”,优先确保服务稳定可用。

✅ 新系统优先选用 Protobuf + gRPC

对接现代基础设施、工具生态更方便,未来维护成本低。

✅ 跨协议通信提供桥接层或统一网关

比如使用 API 网关或网桥做协议转换,让 Thrift 和 Protobuf 服务互通无障碍。


✍️ 最后的话

Thrift 和 Protobuf 之争不是对错问题,而是架构策略与工程现实的平衡

对于像字节跳动这样拥有数万个微服务的大厂来说,“共存”往往比“统一”更现实,也更成熟。

希望这篇文章能帮你更好地理解企业在协议选型上的思路,也欢迎大家留言交流你们团队的做法和思考!


如果你觉得这篇文章有用,不妨 点赞 + 在看 + 分享,也欢迎关注我,后续会持续输出更多底层架构干货、工程设计技巧与开源实践~