API设计实战:REST、gRPC与GraphQL的选型、规范与版本管理

全面对比REST、gRPC、GraphQL三大API范式,深入讲解命名规范、版本管理、错误码设计、分页策略、文档生成等实战技巧,打造开发者友好的API。

引言

API 不是实现细节,API 是产品。它的用户是其他开发者——你的同事、客户公司的前端团队、或调用你服务的第三方。设计糟糕的 API 会让调用方困惑、引发 bug、拖慢团队开发速度;设计良好的 API 像一份优秀文档,调用方几乎无需阅读说明就能正确使用。

当今三大 API 范式:REST(成熟、通用)、gRPC(高性能、强类型)、GraphQL(灵活、客户端驱动)。它们并非互相替代,而是可以共存。本文将系统讲解设计规范、版本管理、错误处理、分页策略和文档生成。


目录


1. REST API 设计规范

1.1 URL 命名规则

REST 将后端数据抽象为资源(Resource),URL 表示资源,HTTP 方法表示操作。

好设计

GET    /api/v1/users            # 列表
GET    /api/v1/users/123        # 单个
POST   /api/v1/users            # 创建
PUT    /api/v1/users/123        # 全量更新
PATCH  /api/v1/users/123        # 部分更新
DELETE /api/v1/users/123        # 删除
GET    /api/v1/users/123/orders # 子资源

反模式/api/getUser?id=123/api/createUser/api/users_list

规则:复数名词、小写连字符、URL 不用动词、子资源最多两层嵌套。

1.2 HTTP 方法语义

方法幂等用途
GET读取
POST创建
PUT全量替换
PATCH部分更新
DELETE删除

1.3 状态码使用

状态码含义场景
200 OK成功GET/PUT/PATCH/DELETE
201 Created创建成功POST
204 No Content成功无返回DELETE
400 Bad Request参数错误校验失败
401 Unauthorized未认证Token 缺失或无效
403 Forbidden无权限权限不足
404 Not Found不存在ID 无效
409 Conflict冲突重复创建
429 Too Many Requests限流请求过快

1.4 HATEOAS

响应中包含下一步操作链接,让客户端动态发现 API 能力:

{
  "id": 123,
  "name": "Alice",
  "_links": {
    "self": { "href": "/api/v1/users/123" },
    "orders": { "href": "/api/v1/users/123/orders" },
    "delete": { "href": "/api/v1/users/123", "method": "DELETE" }
  }
}

HATEOAS 实现复杂,仅在高度动态的系统中推荐。


2. REST API 完整示例

创建用户

POST /api/v1/users HTTP/1.1
Content-Type: application/json
Authorization: Bearer <token>

{ "name": "Alice", "email": "alice@example.com", "role": "admin" }

响应(201 Created):

{
  "id": 123,
  "name": "Alice",
  "email": "alice@example.com",
  "role": "admin",
  "created_at": "2025-11-22T10:00:00Z"
}

错误响应(422):

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request parameters",
    "details": [
      { "field": "email", "issue": "Invalid email format" }
    ]
  }
}

3. gRPC 入门

gRPC 是 Google 开源的高性能 RPC 框架,使用 Protocol Buffers 作为接口定义语言和序列化格式。

syntax = "proto3";
package user.v1;

service UserService {
  rpc GetUser (GetUserRequest) returns (User);
  rpc CreateUser (CreateUserRequest) returns (User);
}

message User {
  int64 id = 1;
  string name = 2;
  string email = 3;
  string created_at = 4;
}

message GetUserRequest { int64 id = 1; }
message CreateUserRequest { string name = 1; string email = 2; }

优势:强类型契约、二进制序列化(比 JSON 小 3-10 倍)、HTTP/2 多路复用、自动生成多语言客户端。


4. gRPC 四种通信模式

1. Unary(一元):普通请求-响应。

rpc GetUser (GetUserRequest) returns (User);

2. Server Streaming:服务器返回数据流。

rpc WatchOrders (WatchOrdersRequest) returns (stream Order);
stream, _ := client.WatchOrders(ctx, &WatchOrdersRequest{UserID: 123})
for {
    order, err := stream.Recv()
    if err == io.EOF { break }
    fmt.Println("New order:", order)
}

3. Client Streaming:客户端发送数据流。

rpc UploadMetrics (stream Metric) returns (UploadSummary);

4. Bidirectional Streaming:双向流,适用于聊天、协作。

rpc Chat (stream ChatMessage) returns (stream ChatMessage);

5. GraphQL 基础

GraphQL 让客户端精确指定需要的字段,避免 REST 的 over-fetching 和 under-fetching。

type User {
  id: ID!
  name: String!
  email: String!
  orders: [Order!]!
}

type Query {
  user(id: ID!): User
  users(limit: Int = 20, cursor: String): UserConnection!
}

type Mutation {
  createUser(input: CreateUserInput!): User!
}

type Subscription {
  orderStatusChanged(userId: ID!): Order!
}

Query 示例

query {
  user(id: "123") {
    name
    orders { id amount }
  }
}

适用:移动端(精准字段)、复杂关联查询、多客户端差异化需求。


6. API 版本管理策略

策略示例优点缺点
URL 路径/api/v1/users直观、易缓存URL 膨胀
查询参数/api/users?version=1简单缓存不友好
HeaderAccept: application/vnd.api.v1+json符合 REST 语义客户端不易感知

推荐:对外 API 用 URL 路径,内部 API 可用 Header。

废弃策略:宣布废弃日期(至少提前 6 个月)→ 返回 Sunset / Deprecation 头 → 提供迁移指南 → 旧版本维护到废弃日。


7. 错误码设计

采用 RFC 7807 Problem Details 标准:

{
  "type": "https://api.example.com/errors/user-not-found",
  "title": "User Not Found",
  "status": 404,
  "detail": "User with ID 123 does not exist",
  "instance": "/api/v1/users/123",
  "trace_id": "abc-123-def",
  "timestamp": "2025-11-22T10:00:00Z"
}

原则

  • 用字符串错误码(USER_NOT_FOUND)而非数字码
  • 每个错误码对应唯一文档页面
  • 区分 4xx(客户端错误)和 5xx(服务器错误)
  • 包含 trace_id 便于排查

8. 分页策略

Offset Pagination

GET /api/v1/users?offset=20&limit=10

优点:简单、可跳页。缺点:插入/删除时重复或遗漏,大偏移性能差。

Cursor Pagination

GET /api/v1/users?cursor=eyJpZCI6MTB9&limit=10
{
  "data": [...],
  "pagination": { "next_cursor": "eyJpZCI6MjB9", "has_more": true }
}

优点:稳定、性能好。缺点:无法跳页。

Keyset Pagination:基于复合索引(如 created_at, id)做 WHERE 比较,适合时间序列,性能最优,无 offset 性能退化。

推荐:对外 API 默认 Cursor,后台管理用 Offset,大数据流用 Keyset。


9. API 文档工具

  • OpenAPI / Swagger:REST 标准规范,可生成客户端、Mock、交互文档
  • gRPC Gateway:将 gRPC 转换为 REST/JSON,便于 Web 客户端
  • GraphiQL / Apollo Studio:GraphQL 交互文档与调试
  • Buf.build:gRPC/protobuf 的现代化 registry

OpenAPI 片段:

paths:
  /api/v1/users/{id}:
    get:
      parameters:
        - { name: id, in: path, required: true, schema: { type: integer } }
      responses:
        '200': { description: User found }

10. 总结对比

维度RESTgRPCGraphQL
协议HTTP/1.1HTTP/2HTTP/1.1
数据格式JSONProtobufJSON
类型系统
性能
客户端灵活性
浏览器支持优秀需 grpc-web优秀
适用对外 API微服务间通信移动端、复杂前端

推荐组合:对外 REST + 内部 gRPC + 移动端 GraphQL,按场景组合。


延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页