工程团队经常耗费整个下午的时间去争论 REST 是否已死,或者 gRPC 是否让其他一切都变得过时。这种争论偏离了重点。你不是在选择最好的协议,而是在选择合适的边界。一个在你的 Kubernetes 集群内部表现出色的协议,一旦交给一千名外部开发者,就会让你窒息。一个能为移动应用节省宝贵带宽的协议,如果你将其开放给任意公共查询,可能会让你的基础设施破产。如果你把这个决定当作一场技术流行度竞赛,你就会埋下架构债务,其影响将比你团队中的每一位成员都长久。
The Boundary Principle
架构关乎权衡,而非争霸。正确的问题从来不是“哪个最快?”或“哪个最新?”,而是“线缆的另一端是谁,他们控制着什么?”协议是边界对象。选错协议不仅会拖慢你的速度,还会让错误在你的系统中根深蒂固多年。
Public APIs: REST 并非乏味,而是负责任的选择
当你的使用者是你从未谋面的外部开发者时,你的 API 就是一个产品,而不仅仅是一个接口。那位开发者可能在凌晨两点进行调试,手里只有 curl 和一个 Postman 集合。如果他们在第一次成功调用之前必须安装自定义客户端库或学习一种 Schema 语言,你就已经失去他们了。
REST 之所以能在此生存,是因为它本身就是 Web 的基石。HTTP 方法、状态码和 JSON 是通用语言。缓存不是事后才考虑的;它是已经存在的基础设施。浏览器、CDN 和边缘缓存原生支持 Cache-Control 请求头和 ETag 验证。你可以将 REST API 放在标准 CDN 之后,无需编写任何缓存逻辑即可立即节省带宽。当公共流量不可预测,且你必须为流出云端的每一 GB 数据付费时,这一点至关重要。
相比之下,GraphQL 给公共边界带来了沉重的税收。公共 GraphQL 端点需要进行查询成本分析、深度限制和复杂度评分,以防止单个粗心或恶意的查询压垮你的数据库。你不仅仅是在交付一个 API;你还在构建一个查询执行引擎、一套限流策略和一个计算计费模型。除非你拥有顶级平台那样的运维实力,否则对于公共暴露面来说,这种开销是鲁莽的。REST 默认就设置了护栏。每个端点只做一件事。消费者获取的是你提供的确切内容,而不是他们能想出来的任何东西。
Internal Services: 掌控整个管道
在组织内部,讨论的重点会发生变化。你同时控制着客户端和服务端。你可以为调用链中的每个服务规定技术栈。这正是 gRPC 发挥价值的地方。
首先,不要把 JSON 视为神圣不可侵犯。Protocol Buffers 的序列化速度大约比 JSON 快三倍。由于采用二进制格式,有效载荷也更小。在繁忙的内部网络中,这些毫秒和兆字节会累积成真金白银,并降低尾部延迟。更重要的是,Protobuf 为你提供了严格的契约。当你更改字段类型或重命名消息时,破坏会在编译时发生,而不是在凌晨三点的生产环境中,当下游服务开始抛出解析异常时。
gRPC 运行在 HTTP/2 之上,因此你可以获得头部压缩、多路复用流和真正的流式语义。如果你在服务之间传输高吞吐量的事件或推送实时更新,服务端流和双向流是原生功能,而不是用胶带粘在请求-响应框架上的长轮询变通方案。
这里有一个硬伤:不要直接将 gRPC 指向浏览器。浏览器的网络模型并不像 gRPC 所期望的那样支持 HTTP/2。你最终不得不将 grpc-web 和像 Envoy 这样的代理嫁接到你的技术栈中,仅仅是为了让浏览器能与后端通信。这不是一个 Bug,而是一个边界信号。将 gRPC 保留在防火墙之后,置于相互信任的服务之间,并将它的调试复杂度视为速度的代价。二进制载荷不像 JSON 那样在日志文件中易于肉眼观察。
Complex UIs and Mobile: GraphQL 的用武之地
现代移动端屏幕是拼凑而成的。一个视图可能需要用户资料,
