Skip to content

API 风格对比

本章导读:REST 不是唯一的 API 风格。理解 RPC(含 gRPC/SOAP)、GraphQL、WebSocket 各自的取舍,你才能回答面试与架构评审中的高频问题:"为什么这个场景选 REST?"本章给出一张决策地图。

1. 四大流派速写

1.1 REST(资源导向)

  • 契约单位:资源 + 统一接口(方法/状态码/媒体类型)。
  • 客户端说"我要这个资源的这个表现",服务器执行并返回。
  • 充分利用 HTTP 生态:缓存、代理、CDN、监控、安全网关。

1.2 RPC(动作导向,含 gRPC)

  • 契约单位:方法签名。PayOrder(orderId, amount) 直接映射为一次远程调用。
  • gRPC 用 Protobuf 强类型 + HTTP/2 多路复用,性能与代码生成能力极强。
  • 传统 SOAP/WebService 是重量级前辈(WSDL),REST 正是作为它的"轻量反叛"而流行。
protobuf
service ArticleService {
  rpc GetArticle(GetArticleRequest) returns (Article);
  rpc PublishArticle(PublishArticleRequest) returns (google.protobuf.Empty);
}

1.3 GraphQL(查询语言导向)

  • 契约单位:类型系统 + 客户端驱动的查询。一个端点 POST /graphql,客户端精确声明要的字段。
  • 解决 REST 两大痛点:over-fetching(返回多余字段)与 under-fetching(N+1 次请求拼装页面)。
graphql
query { article(id: 42) { title author { name } } }

1.4 WebSocket / 消息流(推送导向)

  • 全双工长连接,服务器主动推送。适合协作编辑、行情、聊天、多玩家游戏。

2. 逐维度对比

维度RESTRPC/gRPCGraphQLWebSocket
接口语义资源 + 标准方法自定义方法单端点 + 查询语言消息帧
契约定义OpenAPI(弱类型可选)proto IDL(强类型)SDL 类型系统无标准,自定义协议
缓存HTTP 缓存原生支持不支持(需自建)请求体参与缓存键,难缓存
浏览器/代理友好★★★★★★★★(需 grpc-web)★★★★(本质是 POST)★★
性能(内网服务间)极佳(二进制 + 多路复用 + 流)一般(查询解析开销)极佳
灵活取数/聚合弱(多资源要多次请求)弱(方法固定)极强
移动端弱网优化空间高(按需取字段)
学习/工具生态最成熟微服务领域成熟增长中成熟
权限控制粒度端点 + 字段级需自研方法级字段级 resolver,天然细自研

3. 选型决策地图

是对外公开/第三方集成的 API 吗?
├─ 是 → REST(生态最大、网关友好、OAuth 标准链路)
└─ 否(内部系统)
   ├─ 高频服务间调用、延迟敏感、需要双向流?
   │  └─ 是 → gRPC
   ├─ 页面数据形态多变、由前端团队自主迭代?
   │  └─ 是 → GraphQL(或 REST + BFF 层)
   ├─ 服务器需主动实时推送?
   │  └─ 是 → WebSocket / SSE(REST 管理资源 + SSE 推进度是常见组合)
   └─ 默认 → REST:CRUD 主导、资源模型稳定的业务系统

混合是常态:

  • 支付回调、转账确认等"过程性"操作,REST 社区也允许动词端点(POST /articles/42/publish)或任务子资源——纯粹的"万物皆名词"在工程上并非必须。
  • 大厂典型架构:对外 REST 网关 → 内部 gRPC 微服务 → 个别 GraphQL BFF。REST 的"对外契约"地位并不因内部选型而动摇。

4. REST 的常见批评(诚实面对)

批评回应
N+1 请求:文章 + 作者 + 评论要 3 次请求?expand=author,comments(字段扩展)或 BFF 聚合;GraphQL 确实更优
over-fetching:接口返回整个资源提供 ?fields=title,id 稀疏集(Sparse Fieldsets,JSON:API 概念)
批量写操作别扭(无批量 POST 标准)设计批量端点 POST /articles:batchCreate(Google AIP 风格)或作业资源,见批量操作设计
复杂流程/长事务表达弱把流程建模为资源(/jobs/{id} + 状态轮询/SSE),见实战篇
规范只给原则不给细节,团队各写各的正因如此才需要本教程第 03 篇"设计规范"与 OpenAPI 治理

5. 一个务实的结论

  1. 资源稳定的业务数据(用户、订单、文章)→ REST 建模几乎总是正确答案。
  2. 动作密集、计算服务(转码、AI 推理)→ 把"任务"做成资源(POST /jobs + GET /jobs/{id}),仍是 REST 的扩展而非抛弃。
  3. 强类型内部 RPC 与 REST 外部契约可以并存,不必二选一。

6. 本章小结

  • REST 的核心竞争力不是性能,而是统一接口带来的协议级生态(缓存/网关/安全/可观测性)。
  • 选型依据是"数据形态由谁决定":服务端决定→REST;客户端决定→GraphQL;双方高频互推→WebSocket。
  • REST 的缺陷有成熟的模式化补救(expand 参数、稀疏字段、作业资源),学完后续章节即可落地。

7. 下一步

入门篇到此结束。从下一章开始,我们把 REST 拆成可执行的设计动作——先解决"什么是资源、怎么划分" → 资源与资源层次