4. RESTful vs gRPC 宏观对比:协议栈、性能、序列化、浏览器支持、生态
说实话,做微服务这几年,我被问得最多的问题就是:“到底该选 REST 还是 gRPC?”
每次我都得先反问一句:“你的客户端是浏览器还是后端服务?对延迟有多敏感?”
因为这两个东西,虽然在同一个“远程调用”的赛道上,但本质差得很远。今天咱们就来拉一张大表,彻底拆开它们的底裤。
4.1 协议栈:一个在 HTTP/1.1 上建房子,一个在 HTTP/2 上搭积木
RESTful 通常跑在 HTTP/1.1 之上,消息格式用 JSON 或 XML。每次请求都带完整的请求头,而且 HTTP/1.1 的队头阻塞问题,在并发高的场景下特别明显。我早期做的一个 REST 网关,流量一上来,TCP 连接池就炸了,排查半天发现是浏览器限制了同一域名下的并发连接数。
gRPC 则直接跑在 HTTP/2 上,底层用 Protobuf 二进制流。HTTP/2 的多路复用、头部压缩、流控,天然解决了队头阻塞。更关键的是,gRPC 支持全双工流——服务端可以主动 push 数据,这在实时推送场景里简直是杀手锏。
| 维度 | RESTful (HTTP/1.1 + JSON) | gRPC (HTTP/2 + Protobuf) |
|---|---|---|
| 传输层 | TCP | TCP |
| 应用层协议 | HTTP/1.1 | HTTP/2 |
| 序列化格式 | JSON / XML(文本) | Protocol Buffers(二进制) |
| 消息模式 | 请求-响应(一应一答) | 一元、服务端流、客户端流、双向流 |
| 头部压缩 | 不支持 | HPACK 压缩 |
| 默认端口 | 80 / 443 | 443(通常用 TLS) |
4.2 性能:gRPC 快,但快多少?
我当年在金融项目里做过一个基准测试:同样一个“查询账户余额”的接口,REST 用 JSON 序列化、HTTP/1.1 长连接;gRPC 用 Protobuf、HTTP/2 多路复用。结果 gRPC 的吞吐量高了 3~4 倍,延迟降低了 40% 左右。
为什么?
- 序列化:Protobuf 是二进制,体积比 JSON 小 30%~60%,解析速度也快一个量级。
- 头部压缩:HTTP/2 用 HPACK 压缩请求头,第一次稍慢,后续请求头可以复用,省掉大量冗余字节。
- 多路复用:一个 TCP 连接上可以同时跑成百上千个请求,不用像 HTTP/1.1 那样排队。
注意:性能提升不是免费的。gRPC 对网络丢包和延迟更敏感,因为 HTTP/2 的流控和优先级机制在弱网环境下会退化。我曾经在公网跨区域调用时,gRPC 反而比 REST 更慢,原因是连接重试和流控导致的额外开销。
4.3 序列化方式:JSON 的“人眼可读” vs Protobuf 的“机器效率”
序列化是两者最直观的差别。REST 用 JSON,你打开浏览器就能看到数据是什么。调试一个 REST 接口,curl 一下,肉眼扫一遍,搞定。
gRPC 用 Protobuf,返回的是二进制数据。你要用专门的工具(grpcurl、envoy、或者 gRPC UI)才能看到内容。部署的时候,服务端和客户端必须持有同一份 .proto 文件,版本不一致就崩。
曾经踩过的坑:有一次团队里有人改了 proto 文件中字段的编号,但服务端没更新,结果客户端反序列化出了完全错误的数据。幸好有单元测试兜底,不然线上就炸了。所以我的习惯是:所有 proto 变更必须走 code review,且编号不能复用。
| 特性 | JSON | Protocol Buffers |
|---|---|---|
| 可读性 | 高,人类可读 | 低,需工具解码 |
| 体积 | 大(冗余字段名) | 小(二进制 + 编号映射) |
| 编解码性能 | 慢(反射 + 文本解析) | 快(直接内存映射) |
| 向后兼容 | 灵活(加字段不影响) | 严格(需遵循 proto 版本规则) |
| 多语言生成 | 各种库均可手动解析 | protoc 工具自动生成桩代码 |
警告:如果你的团队对 proto 不熟悉,或者频繁需要人工调试接口,请三思。JSON 虽然慢,但调试效率能省下你一天的时间。
4.4 浏览器支持:REST 是亲儿子,gRPC 是干儿子
这是个很现实的问题。所有浏览器都原生支持 fetch、XMLHttpRequest,处理 REST/JSON 毫不费力。而 gRPC 在浏览器端就是个灾难——因为浏览器没法直接控制 HTTP/2 的原始帧,所以 gRPC-Web 只是一个补丁方案,需要额外的代理(比如 Envoy、gRPC-Web proxy)把 HTTP/2 转成浏览器能理解的 HTTP/1.1 或 gRPC-Web 特有格式。
我的建议很简单:
- 如果前端是 Web 浏览器 → 选 REST(或者 GraphQL)。
- 如果前端是移动 App / 后端微服务 → 可以用 gRPC,但要做好容错。
- 如果非要全栈 gRPC → 用 gRPC-Web + Envoy,但要做好心理准备:调试困难、CORS 配置繁琐、DevTools 不支持。
4.5 生态成熟度:REST 经过了 20 年考验,gRPC 还在爬坡
REST 从 2000 年 Roy Fielding 的算起,已经有二十多年历史。相关的框架、中间件、监控、安全策略、工具链,几乎应有尽有。你要做限流?Nginx + lua 就能搞定。做 API 文档?Swagger / OpenAPI 几乎是标准。做测试?Postman / Insomnia 直接导入。
gRPC 是 Google 2015 年开源的,虽然背靠 Google 的背书和 Kubernetes、etcd 等明星项目,但生态还在成长。比如:
- 负载均衡:gRPC 依赖客户端负载均衡(基于 DNS 或 xDS),传统的 SLB 不太适用。
- 监控:gRPC 内置了 prometheus 和 opencensus 集成,但自定义拦截器需要写不少代码。
- 调试:没有像 Postman 那样的一键工具,grpcurl 和 grpcui 可以应急,但体验远不如 REST。
一句话总结:gRPC 在内部微服务、高吞吐、实时流场景下是王者;REST 在对外开放、浏览器、快速迭代场景下是基石。选哪个,取决于你的客户端是谁。