最近发现字节跳动的go框架hertz中,同时支持 Thrift 和 Protobuf,这就很好奇,为啥还要支持Thrift?直接使用Protobuf不香吗?字节跳动这么大的公司,为什么要容忍两套协议共存的“复杂性”?
不仅增加的学习的难度,也增加了项目的复杂度,直接一套Protobuf不好嘛。
下面来看下Thrift 和 Protobuf的区别是什么?有什么区别和联系。
一、Thrift 和 Protobuf 到底是什么?
先来打个比方:
-
Thrift 更像是“包办婚姻”:你只要写好一份接口定义,它就自动帮你生成服务端、客户端代码,甚至连传输协议和序列化格式都一手包办。你说你要服务A调用服务B?没问题,全都安排上。
-
Protobuf 更像是“自由恋爱”:它本质上是一个数据序列化工具,你定义好数据结构,它帮你压缩得又小又快,但怎么传、怎么收,得你自己决定。这也带来了更多的灵活性。
🧩 技术特点快速对比
| 特性 | Thrift | Protobuf |
|---|---|---|
| 定位 | 全家桶: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 之争不是对错问题,而是架构策略与工程现实的平衡。
对于像字节跳动这样拥有数万个微服务的大厂来说,“共存”往往比“统一”更现实,也更成熟。
希望这篇文章能帮你更好地理解企业在协议选型上的思路,也欢迎大家留言交流你们团队的做法和思考!
如果你觉得这篇文章有用,不妨 点赞 + 在看 + 分享,也欢迎关注我,后续会持续输出更多底层架构干货、工程设计技巧与开源实践~