API设计基础Skill api-design-fundamentals

API设计基础技能用于指导如何设计有效的API,涵盖协议选择(如REST、GraphQL、gRPC)、资源建模、端点设计和最佳实践。适用于开发者和架构师,提升API的可用性、一致性和开发者体验。关键词:API设计,REST API,GraphQL,gRPC,协议比较,资源命名,错误处理,API进化,开发者体验。

架构设计 0 次安装 0 次浏览 更新于 3/11/2026

名称: api-design-fundamentals 描述: 用于设计API、在REST/GraphQL/gRPC之间选择,或理解API设计最佳实践时使用。涵盖协议选择、资源建模和API模式。 允许工具: Read, Glob, Grep

API设计基础

设计有效API的指南,包括协议选择、资源建模和最佳实践。

何时使用此技能

  • 在REST、GraphQL和gRPC之间选择
  • 设计资源模型和端点
  • 理解API设计最佳实践
  • 创建一致的API约定
  • 为开发者体验设计

协议比较

REST(表述性状态转移)

最适合: CRUD操作、公共API、广泛客户端兼容性

特点:
- 资源导向(名词,非动词)
- HTTP方法映射到操作(GET、POST、PUT、DELETE)
- 无状态
- 可缓存的响应
- 自描述消息

示例:
GET    /users          - 列出用户
GET    /users/{id}     - 获取用户
POST   /users          - 创建用户
PUT    /users/{id}     - 更新用户
DELETE /users/{id}     - 删除用户

优点:

  • 简单,广泛理解
  • 优秀的缓存支持
  • 与任何HTTP客户端兼容
  • 适合公共API

缺点:

  • 过度获取(获取超出需要的数据)
  • 不足获取(需要多个请求)
  • 无内置模式/类型

GraphQL

最适合: 复杂数据需求、移动应用、聚合多个服务

特点:
- 单一端点
- 客户端指定所需数据
- 强类型模式
- 内省支持
- 通过订阅支持实时

示例:
查询 {
  用户(id: "123") {
    名称
    邮箱
    帖子(限制: 5) {
      标题
      评论 { 数量 }
    }
  }
}

优点:

  • 无过度/不足获取
  • 强类型和模式
  • 优秀的开发者工具
  • 无版本演化

缺点:

  • 缓存复杂性
  • N+1查询问题
  • 学习曲线
  • 不适合简单API

gRPC

最适合: 内部微服务、高性能、多语言系统

特点:
- 协议缓冲区(二进制格式)
- HTTP/2传输
- 双向流
- 代码生成
- 强类型

示例(proto):
服务 用户服务 {
  rpc 获取用户(获取用户请求) 返回 (用户);
  rpc 列出用户(列出用户请求) 返回 (流 用户);
  rpc 创建用户(创建用户请求) 返回 (用户);
}

优点:

  • 高性能(二进制、HTTP/2)
  • 强合约(protobuf)
  • 双向流
  • 适合微服务

缺点:

  • 浏览器支持有限(需grpc-web)
  • 非人类可读
  • 学习曲线较陡
  • 调试更复杂

协议选择指南

决策树:

这是面向外部开发者的公共API吗?
├── 是 → REST(最广泛兼容性)
└── 否
    └── 客户端需要灵活查询吗?
        ├── 是 → GraphQL
        └── 否
            └── 性能关键吗?
                ├── 是 → gRPC
                └── 否 → REST或GraphQL
因素 REST GraphQL gRPC
公共API ✅ 最佳 ⚠️ 可能 ❌ 差
移动应用 ⚠️ 可 ✅ 最佳 ⚠️ 有限
微服务 ⚠️ 可 ⚠️ 可 ✅ 最佳
实时 ⚠️ WebSocket ✅ 订阅 ✅ 流
浏览器支持 ✅ 原生 ✅ 原生 ⚠️ grpc-web
缓存 ✅ 易 ⚠️ 复杂 ❌ 手动
学习曲线 ✅ 低 ⚠️ 中 ⚠️ 中

REST API设计最佳实践

资源命名

做:
- 使用名词,非动词:/users, /orders, /products
- 使用复数形式:/users(非/user)
- 使用连字符:/user-profiles(非/userProfiles)
- 嵌套关系:/users/{id}/orders

不做:
- /getUsers, /createOrder(动词)
- /user(单数)
- /user_profiles(URL中的蛇形命名)

HTTP方法

方法 目的 幂等 安全
GET 读取资源
POST 创建资源
PUT 替换资源
PATCH 部分更新 否*
DELETE 删除资源

*PATCH根据实现可能幂等

状态码

代码 含义 何时使用
200 OK 成功GET、PUT、PATCH
201 已创建 成功POST
204 无内容 成功DELETE
400 错误请求 无效请求体
401 未授权 缺失/无效认证
403 禁止 权限不足
404 未找到 资源不存在
409 冲突 资源冲突
422 不可处理 验证失败
429 过多请求 速率限制
500 服务器错误 意外错误

分页

基于偏移(简单,但在大规模有问题):
GET /users?offset=20&limit=10

基于游标(推荐用于大型数据集):
GET /users?cursor=eyJpZCI6MTAwfQ&limit=10

响应:
{
  "data": [...],
  "pagination": {
    "next_cursor": "eyJpZCI6MTEwfQ",
    "has_more": true
  }
}

过滤和排序

过滤:
GET /products?category=electronics&price_min=100&price_max=500

排序:
GET /products?sort=price:asc,name:desc

字段选择(部分响应):
GET /users?fields=id,name,email

错误响应

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "无效请求参数",
    "details": [
      {
        "field": "email",
        "message": "无效邮箱格式"
      }
    ],
    "request_id": "req_abc123"
  }
}

GraphQL最佳实践

模式设计

# 使用清晰、描述性类型
类型 用户 {
  id: ID!
  email: String!
  profile: 用户档案
  posts(first: Int, after: String): 帖子连接!
}

# 使用连接进行分页
类型 帖子连接 {
  edges: [帖子边!]!
  pageInfo: 页信息!
}

# 使用输入类型进行突变
输入 创建用户输入 {
  email: String!
  name: String!
}

查询复杂度限制

防止昂贵查询:
- 深度限制(最大嵌套级别)
- 复杂度评分(为字段分配成本)
- 查询超时
- 按客户端速率限制

N+1预防

使用DataLoader模式:
- 批量同类型请求
- 单个请求内缓存
- 防止N+1数据库查询

gRPC最佳实践

服务设计

// 保持消息专注
消息 用户 {
  string id = 1;
  string email = 2;
  string name = 3;
}

// 使用请求/响应包装器
消息 获取用户请求 {
  string id = 1;
}

消息 获取用户响应 {
  用户 user = 1;
}

// 支持流处理大型数据集
服务 用户服务 {
  rpc 获取用户(获取用户请求) 返回 (获取用户响应);
  rpc 列出用户(列出用户请求) 返回 (流 用户);
}

错误处理

使用标准gRPC状态码:
- OK (0): 成功
- INVALID_ARGUMENT (3): 错误请求
- NOT_FOUND (5): 资源缺失
- PERMISSION_DENIED (7): 禁止
- INTERNAL (13): 服务器错误
- UNAVAILABLE (14): 服务不可用

API进化

向后兼容规则

安全更改(向后兼容):
- 添加新端点
- 添加可选字段
- 添加新枚举值(在末尾)
- 放宽验证规则

破坏性更改(避免):
- 移除端点
- 移除字段
- 更改字段类型
- 重命名字段
- 添加必填字段

弃用策略

1. 标记为弃用(添加头部/注释)
2. 文档迁移路径
3. 设置日落日期
4. 监控使用
5. 日落后移除

相关技能

  • rate-limiting-patterns - API保护
  • idempotency-patterns - 可靠API
  • api-versioning - API进化