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)
传输层TCPTCP
应用层协议HTTP/1.1HTTP/2
序列化格式JSON / XML(文本)Protocol Buffers(二进制)
消息模式请求-响应(一应一答)一元、服务端流、客户端流、双向流
头部压缩不支持HPACK 压缩
默认端口80 / 443443(通常用 TLS)
我的经验:如果你的客户端是浏览器,别挣扎,老老实实用 REST(或 GraphQL)。gRPC-Web 虽然能用,但生态和调试工具远不如 REST 顺手。

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,且编号不能复用。

特性JSONProtocol 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 在对外开放、浏览器、快速迭代场景下是基石。选哪个,取决于你的客户端是谁。

RESTful vs gRPC 宏观对比 RESTful 传输协议:HTTP/1.1 序列化:JSON(文本) 消息模式:一元请求-响应 浏览器支持:原生(优秀) 生态成熟度:非常高(20年+) gRPC 传输协议:HTTP/2 序列化:Protobuf(二进制) 消息模式:一元/流(4种) 浏览器支持:需 gRPC-Web + 代理 生态成熟度:中等(Growing) 选择的本质:看客户端是谁 浏览器 / 对外 API → RESTful(优先) 服务间调用 / 实时流 / 高吞吐 → gRPC(优先)