2. RESTful API 设计原则

REST(Representational State Transfer,表述性状态转移)是一种架构风格,而非具体协议。它由 Roy Fielding 于 2000 年在其博士论文中提出,强调通过资源(Resource)的表述(Representation)来驱动状态转移(State Transfer)。在微服务架构中,RESTful API 是服务间通信与对外暴露接口的主流选择之一。

核心认知:REST 不是标准,而是一组设计约束。遵循这些约束的 API 被称为 RESTful API。其核心价值在于统一接口、无状态和资源导向。

2.1 REST 架构风格六大约束

一个符合 REST 风格的架构必须满足以下六大约束条件:

约束 描述 微服务中的意义
客户端-服务器 分离用户界面与数据存储,提升可移植性与可扩展性 服务端可独立演进,客户端无需关心数据存储细节
无状态 每个请求包含所有必要信息,服务器不保存客户端上下文 服务实例可水平扩展,任意节点处理任意请求
可缓存 响应隐式或显式标记为可缓存或不可缓存 减少重复请求,降低服务负载,提升响应速度
统一接口 通过资源标识、表述操作、自描述消息、HATEOAS 实现 降低服务耦合,客户端与服务器按标准契约交互
分层系统 客户端无法直接感知是否与端服务器或中间层通信 支持负载均衡、反向代理、网关等中间件透明介入
按需代码(可选) 服务器可向客户端传输可执行代码(如 JavaScript) 较少在微服务 API 中使用,通常保持纯数据接口
实践要点:在微服务网关层,无状态约束要求 Token、Session ID 等认证信息必须由客户端在每次请求中携带,不能依赖服务端内存存储。

2.2 资源导向设计

资源是 REST 的核心抽象。资源导向设计(Resource-Oriented Design)要求将业务实体抽象为名词,并通过 URI 进行唯一标识。URI 只描述资源,不描述操作。

  • 资源命名:使用复数名词,如 /users、/orders、/products。
  • 层级关系:通过路径表达从属关系,如 /users/{userId}/orders。
  • 查询参数:用于过滤、排序、分页,如 /orders?status=active&page=1。
  • 避免动词:不要出现 /getUser、/createOrder 等动词路径。
# 反例(非资源导向)
GET /api/getUser?id=123
POST /api/createOrder
POST /api/deleteProduct?id=456

# 正例(资源导向)
GET /api/users/123
POST /api/orders
DELETE /api/products/456
常见误区:将 CRUD 操作直接映射为 URI 动词。REST 的核心是资源状态转移,而非远程过程调用(RPC)。URI 只标识资源,操作由 HTTP 动词表达。

2.3 HTTP 动词与 CRUD 映射

HTTP 协议定义了一组动词(Methods),用于对资源执行操作。RESTful API 严格遵循动词语义:

HTTP 动词 CRUD 操作 幂等性 安全性 请求体 响应体
GET 读取(Read) 是 是 无 资源表述
POST 创建(Create) 否 否 资源表述 新资源 URI / 表述
PUT 整体替换(Update) 是 否 完整资源表述 更新后资源表述
PATCH 部分更新(Partial Update) 否 否 部分字段表述 更新后资源表述
DELETE 删除(Delete) 是 否 无 空 / 确认消息
幂等性说明:多次执行同一请求,资源状态与第一次执行后相同。GET、PUT、DELETE 是幂等的;POST 每次可能创建新资源,不幂等。PATCH 可能因并发冲突而不幂等。

2.4 HTTP 状态码语义

状态码是服务器对请求结果的标准化反馈。正确使用状态码能让客户端无需解析响应体即可判断请求结果。

分类 状态码 含义 典型场景
2xx 成功 200 OK 请求成功 GET、PUT、PATCH 成功返回资源
201 Created 资源创建成功 POST 创建新资源后返回
204 No Content 请求成功,无返回内容 DELETE 成功,或无需返回体的 PUT
4xx 客户端错误 400 Bad Request 请求格式错误或参数无效 JSON 解析失败、校验不通过
404 Not Found 资源不存在 URI 对应的资源未找到
409 Conflict 资源当前状态冲突 版本冲突、唯一约束违反
5xx 服务端错误 500 Internal Server Error 服务器内部错误 未捕获异常、数据库连接失败
503 Service Unavailable 服务暂时不可用 过载、熔断、维护中
反模式:所有成功请求都返回 200 OK,错误信息放在响应体中的 code 字段。这破坏了 HTTP 状态码的语义,增加了客户端解析复杂度。应优先使用标准状态码。

2.5 HATEOAS 概念

HATEOAS(Hypermedia As The Engine Of Application State,超媒体作为应用状态引擎)是 REST 架构风格中统一接口约束的关键组成部分。它要求服务器在响应中提供超媒体链接,引导客户端发现并执行后续可能的操作。

  • 核心思想:客户端无需预先知道 API 的 URL 结构,通过响应中的链接动态导航。
  • 实现方式:在 JSON 或 XML 响应中包含 links 或 _links 字段,每个链接包含 rel(关系)、href(URI)、method(动词)等信息。
  • 价值:降低客户端与服务端的耦合,服务端可自由调整 URI 结构而不破坏客户端。
{
  "orderId": "ord-2024-001",
  "status": "pending",
  "totalAmount": 299.00,
  "_links": {
    "self": { "href": "/api/orders/ord-2024-001", "method": "GET" },
    "pay": { "href": "/api/orders/ord-2024-001/payment", "method": "POST" },
    "cancel": { "href": "/api/orders/ord-2024-001", "method": "DELETE" },
    "items": { "href": "/api/orders/ord-2024-001/items", "method": "GET" }
  }
}
微服务实践:在微服务网关层实现 HATEOAS 时,链接的 href 应指向网关入口,而非直接暴露内部服务地址。这有助于统一入口、安全控制和版本管理。

2.6 RESTful API 设计流程总览

以下 SVG 图展示了从业务实体到 RESTful API 的完整设计流程:

RESTful API 资源导向设计流程 1. 识别业务实体 用户、订单、商品 2. 抽象为资源 /users, /orders 3. 设计 URI 结构 层级、参数、版本 4. 映射 GET/POST/PUT/DELETE 5. 定义资源表述 JSON Schema / Protobuf 6. 配置状态码语义 200 / 201 / 400 / 404 7. 添加 HATEOAS 链接 _links 导航 设计原则总结 • 资源是名词,操作是动词(HTTP 方法) • URI 只标识资源,不包含操作 • 状态码传递语义,响应体传递数据 输出:RESTful API 设计文档

2.7 REST 与 gRPC 设计哲学对比

在微服务双协议桥接场景中,理解 REST 与 gRPC 的设计差异至关重要:

维度 RESTful API gRPC
接口定义 隐式约定(文档驱动) 显式契约(Proto 文件驱动)
数据格式 JSON / XML(文本,自描述) Protobuf(二进制,高效紧凑)
操作模型 资源 CRUD(名词 + 动词) 服务方法调用(动词 + 参数)
状态管理 无状态,每次请求独立 支持流式(Server/Client/Bidirectional)
浏览器支持 原生支持 需 gRPC-Web 或 Envoy 代理
适用场景 外部 API、Web 前端、开放接口 内部服务间通信、高性能场景
桥接策略:在微服务架构中,通常对外暴露 RESTful API(通过 API 网关),内部服务间通信使用 gRPC。网关层负责协议转换、认证、限流等横切关注点。

2.8 RESTful API 设计检查清单

以下清单可用于评审 API 设计是否符合 REST 原则:

  • 资源命名:使用复数名词,路径层级不超过 3 层。
  • 动词使用:GET 不修改资源状态,POST 用于创建,PUT 用于整体替换,DELETE 用于删除。
  • 状态码:成功使用 2xx,客户端错误使用 4xx,服务端错误使用 5xx。
  • 版本管理:通过 URI 前缀(/v1/)或请求头(Accept: application/vnd.api+json;version=1)管理。
  • 分页:列表接口支持 page 和 size 参数,响应中包含总记录数。
  • 错误响应:统一错误格式,包含 error、message、details 字段。
  • HATEOAS:关键资源响应中包含 _links 导航。
  • 安全性:使用 HTTPS,敏感操作需认证授权。
推荐工具:使用 OpenAPI 3.0(Swagger)规范描述 RESTful API,配合 Stoplight、Redoc 等工具生成文档和 Mock 服务。在双协议桥接场景中,OpenAPI 文档可作为 REST 侧的契约,与 gRPC 的 Proto 文件形成互补。