Skip to content

API Design(API 设计) ​

解决什么问题:让跨服务 / 跨团队的接口"好调用、好演化、好测试"—— 设计差的 API = 调用方吐槽、改一字段全链路崩、版本混乱。 设计好的 API = 接口稳定、语义清晰、错误明确、演化有路径。

它是什么 ​

API Design 是 L2 设计层关于外部接口契约的工程方法——包括:

  1. RESTful API 设计(HTTP + JSON,主流)
  2. RPC / gRPC API(强类型 + 高性能)
  3. GraphQL API(前端驱动的灵活查询)
  4. API 风格选择:REST vs RPC vs GraphQL vs 混合

核心问题:

  • 资源如何抽象?(URL 设计 / protobuf message)
  • 状态如何表达?(HTTP status / gRPC status)
  • 错误如何传达?(错误码 + 错误消息)
  • 版本如何演化?(URL 版本 / Header 版本 / 语义版本)
  • 演化如何兼容?(新增字段 OK,删除字段 / 改类型危险)

SE@G Ch 18:"The most important principle of API design is consistency. Once you've chosen a style, apply it everywhere."

V2 视角(V2.7 B4 段 4 抽象 + B3 段 5 团队可拥有):API 是 BC 之间的"宪法"——一旦发布,每个调用方都是你的客户,破坏兼容 = 法律纠纷。

关键属性 ​

属性值/含义
契约OpenAPI / protobuf IDL / GraphQL SDL
一致性命名 / 错误 / 分页 / 过滤全 API 一致
版本URL 路径 / Header / 媒体类型
兼容只能加不能减(减 = 主版本升级)
错误错误码 + 消息 + 详情(结构化)
文档自动生成 + 人类可读 + 范例
反模式一次性 API、用着用着改字段、错误码不统一
判错标志文档和实现不一致 / 调用方要看代码

怎么用 ​

场景 1:RESTful API 设计 ​

资源抽象:

GET    /orders                ← 列表
POST   /orders                ← 创建
GET    /orders/{id}           ← 单个
PATCH  /orders/{id}           ← 部分更新
DELETE /orders/{id}           ← 删除

GET    /orders/{id}/items     ← 子资源
POST   /orders/{id}/items     ← 添加子资源

命名原则:

  • 资源用复数名词(/orders 不 /order)
  • 不用动词(/getOrder → ❌,GET /orders/{id} → ✅)
  • 用连字符不用下划线(/order-items ✅)

场景 2:OpenAPI 契约优先(API-First) ​

yaml
# openapi.yaml
openapi: 3.1.0
info:
  title: Order API
  version: 2.1.0
paths:
  /orders:
    post:
      operationId: placeOrder
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PlaceOrderRequest'
      responses:
        '201':
          description: Order placed
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OrderResponse'
        '400': { $ref: '#/components/responses/ValidationError' }
        '409': { $ref: '#/components/responses/ConflictError' }
        '422': { $ref: '#/components/responses/BusinessError' }
components:
  schemas:
    PlaceOrderRequest:
      type: object
      required: [customerId, items]
      properties:
        customerId: { type: string, format: uuid }
        items:
          type: array
          minItems: 1
          items: { $ref: '#/components/schemas/OrderItemInput' }

契约优先的好处:

  • 代码生成(Server Stub + Client SDK)
  • 文档自动生成
  • 前后端并行开发(基于契约)
  • 测试自动生成

场景 3:版本演化策略 ​

V2 B7 段 4 演化视角:API 演化有 4 种策略:

1. URL 路径版本        /v1/orders /v2/orders    ← 最简单,推荐
2. Header 版本         Accept: application/vnd.myapi.v2+json
3. 媒体类型版本        Content-Type: application/vnd.myapi.v2+json
4. 无版本(持续演化)  ← 只有内部 API 可用

演化兼容性规则:

  • ✅ 可以:加字段、加端点、加可选参数
  • ⚠️ 慎重:删字段(客户端可能还在读)、改字段类型
  • ❌ 必须新版本:删端点、改 URL 语义、改必填

示例——给 Order 加 notes 字段:

diff
  {
    "id": "ord-001",
    "customerId": "cus-123",
    "items": [...],
+   "notes": "VIP 客户优先发货"  ← 新字段,兼容
  }

老客户端忽略 notes → 无破坏。新客户端读 notes → 受益。

场景 4:结构化错误响应 ​

json
{
  "error": {
    "code": "ORDER_INSUFFICIENT_STOCK",
    "message": "商品 SKU-001 库存不足",
    "details": {
      "productId": "SKU-001",
      "requested": 10,
      "available": 3
    },
    "traceId": "abc-123-xyz",
    "documentation": "https://docs.example.com/errors/ORDER_INSUFFICIENT_STOCK"
  }
}

HTTP status 语义:

  • 400:参数错(语法 / 验证)
  • 401 / 403:认证 / 授权
  • 404:资源不存在
  • 409:状态冲突(已支付 / 已发货)
  • 422:业务规则违反(库存不足)
  • 429:限流
  • 5xx:服务端故障

V2 B5 段 3 "反馈":错误响应是反向反馈——告诉调用方"什么错了、为什么、怎么办"。

场景 5:gRPC vs REST 选型 ​

场景                          → 推荐
浏览器 / 移动端 / 公开 API    → REST + JSON
服务间高频调用 / 强类型需求   → gRPC
流式(双向 / 长连接)         → gRPC streaming
前端驱动灵活查询             → GraphQL
异构系统集成(第三方)        → REST + JSON

gRPC 的优势:强类型 IDL(protobuf)、二进制高性能、双向流、内置超时 / 重试 / 熔断。 gRPC 的劣势:浏览器不能直接调(需要 grpc-web 网关)、调试不直观。

常见误区 ​

  1. "API 设计 = URL 设计"——错。URL 只是表层,契约 + 错误 + 版本 + 演化才是核心
  2. "暴露数据库表结构"——错。API 是业务抽象,不是数据 schema。Order 是 API,不是 table_orders
  3. "加字段 = 改字段"——错。只能加字段,改类型必须新版本
  4. "错误码 = HTTP status"——错。HTTP status 是协议层,业务错误应该用业务错误码(如 ORDER_INSUFFICIENT_STOCK),HTTP status 配 422
  5. "API 文档一次性写完"——错。API 文档 = 契约,代码改 = 文档改。用 OpenAPI 自动生成
  6. "REST = 不用 RPC"——半对。REST 适合外部,gRPC 适合内部。混合用是常态

关键洞察 ​

API 是系统间的"宪法",设计原则比 URL 美观重要 100 倍。

一致性、兼容性、可演化性——三个特性决定了 API 的"寿命"。

V2 B4 抽象 + B7 演化 的组合拳: 把 API 当成"抽象端口"——业务核心不依赖 API 具体格式, API 当作业务边界的"宪法",永远可演化、永远兼容。

相关链接 ​

从名家方法论与工程化思路中蒸馏出自己的工程体系。