REST 架构风格
2000 年,Roy Fielding 在其博士论文中提出了 表现层状态转换(Representational State Transfer,REST)。作为一种分布式超媒体系统的架构风格,REST 并非一种协议或标准,而是一组设计原则。其中最核心、也最容易被忽视的一条约束是 HATEOAS(Hypermedia As The Engine Of Application State)——超媒体作为应用状态的引擎。
HATEOAS:REST 的灵魂
HATEOAS 要求服务端返回的响应中包含指向相关操作的链接,客户端通过这些链接发现和执行下一步操作,而非事先约定好 URL 结构。理想情况下,客户端只需要知道一个入口 URL,其他所有交互路径都由服务端通过超媒体动态提供。
这个理念早在 Web 诞生之初就深植于 HTML 之中——网页上的链接驱动着用户在网站中的导航。但大多数所谓的 "RESTful API" 只是把 JSON 当作传输格式,客户端需要事先了解所有端点结构,本质上与 RPC 并无区别。这正是 Fielding 所批评的「REST 不是 RPC」的真正含义。
RESTful API 设计规范
尽管 HATEOAS 很少被完整实现,业界仍然形成了一套实用的 RESTful API 设计规范。
资源命名遵循名词复数形式,而非动词:
HTTP 动词对应 CRUD 操作:
状态码必须准确表达响应含义,而不是用 200 或 500 敷衍了事:
常见反模式
REST 的普及伴随着大量反模式的涌现。
版本号放在 URL 中是最常见的误区。/v1/users 和 /v2/users 意味着客户端需要管理多个版本的接口逻辑。RESTful 的版本管理应该通过内容协商(Content Negotiation)实现:
过度嵌套的 URL 会导致脆弱的客户端代码。/users/123/orders/456/items/789 这样的路径意味着客户端必须知道完整的资源层级关系。更好的做法是让每个资源都可以独立寻址:
响应结构不一致是另一个常见问题。成功时返回数据,失败时返回错误消息的格式因人而异。应该定义统一的错误响应结构:
与 GraphQL、gRPC 的竞争关系
REST、GraphQL 和 gRPC 分别代表了 API 设计的三种哲学。
REST 的优势在于简单性和 HTTP 原生支持:不需要特殊的客户端库,可以直接在浏览器和任何 HTTP 工具中测试。缓存机制成熟,与 CDN 天然兼容。但过度获取(Over-fetching)和获取不足(Under-fetching)问题在实际使用中确实存在。
GraphQL 将数据选择权交给客户端,适合数据需求复杂、多个前端需要不同数据视图的场景。但它增加了架构复杂度,需要额外的 Schema 设计和 DataLoader 实现。
gRPC 基于 Protocol Buffers,提供高效的二进制序列化和完整的 RPC 语义,适合服务间通信和强类型契约的场景。但不适合浏览器直接调用,在 API 公开化方面不如 REST。
这三种方案并非互斥,很多大型系统会组合使用:面向外部合作伙伴的公开 API 使用 REST,内部服务间通信使用 gRPC,数据密集型的 BFF 层使用 GraphQL。