4. Error Budget API 设计原则

Error Budget API 是 SRE 体系中的核心控制面接口,其设计质量直接决定变更窗口的自动化程度与恢复流程的可靠性。本章从 RESTful 规范、幂等性、限流熔断、错误码四个维度展开,确保 API 在生产环境中可运维、可观测、可容错。

4.1 RESTful 设计规范

Error Budget API 遵循资源导向的 RESTful 风格,将 Error Budget 视为一级资源,通过标准 HTTP 动词表达操作意图。

HTTP 方法 资源路径 语义 幂等
GET /api/v1/budgets/{service} 查询指定服务的 Error Budget 余额 是
POST /api/v1/budgets/{service}/consume 消耗预算(触发变更窗口) 否(需幂等令牌)
POST /api/v1/budgets/{service}/restore 恢复预算(回滚/补偿) 否(需幂等令牌)
GET /api/v1/budgets/{service}/history 获取预算变更历史 是
命名规范:资源路径使用复数名词(budgets),服务名作为路径参数,动词通过 HTTP 方法表达。避免在路径中使用动词如 /consumeBudget,而是用 POST + 子资源 /consume。

4.2 幂等性设计

在变更窗口和备份恢复场景中,网络重试可能导致预算重复消耗或重复恢复。幂等性设计是防止状态不一致的关键防线。

  • 幂等令牌(Idempotency-Key):客户端在 POST 请求头中携带全局唯一令牌,服务端缓存该令牌的处理结果。重复请求直接返回缓存结果,不执行实际逻辑。
  • 条件更新(Optimistic Locking):使用版本号或时间戳字段,更新时校验当前版本与请求版本一致,避免并发覆盖。
  • 天然幂等操作:GET、PUT、DELETE 方法本身幂等;POST 必须配合幂等令牌或业务唯一键。
// 幂等令牌校验伪代码
POST /api/v1/budgets/gateway/consume
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000

// 服务端处理逻辑
if cache.exists(idempotencyKey):
    return cache.get(idempotencyKey)
else:
    result = consumeBudget(service, amount)
    cache.set(idempotencyKey, result, ttl=3600)
    return result
避坑:幂等令牌的 TTL 必须大于客户端最大重试超时时间。建议设置为 1 小时,并在响应头中返回 Idempotency-Key-Expires 字段,方便客户端判断。

4.3 限流与熔断

Error Budget API 是变更窗口的入口,一旦被突发流量打满,可能导致整个变更流程失控。限流和熔断是保护 API 自身稳定性的核心手段。

4.3.1 限流策略

维度 限流粒度 阈值示例 响应方式
全局 所有服务共享 1000 req/s 429 Too Many Requests
服务级 按 service 路径参数 100 req/s 429 + Retry-After
用户级 按 或 20 req/s 429 + X-RateLimit-Reset

4.3.2 熔断机制

当后端存储(如 Redis/MySQL)或下游依赖出现连续错误时,熔断器自动打开,快速失败而非等待超时。

  • 关闭状态:正常处理请求,统计错误率。
  • 打开状态:错误率超过阈值(如 50%),直接拒绝请求,返回 503 Service Unavailable。
  • 半开状态:经过冷却时间(如 30s),允许少量探测请求,成功则关闭熔断器,失败则重新打开。
熔断器状态机 关闭 (Closed) 正常处理请求 打开 (Open) 快速失败 半开 (Half-Open) 探测请求 错误率 > 50% 冷却超时 探测成功 → 关闭 探测失败 → 重新打开 熔断参数配置建议 • 错误率阈值:连续 10 秒内错误率 > 50% • 冷却时间:30 秒(可根据 Error Budget 剩余量动态调整) • 半开探测数:3 个请求全部成功则关闭熔断器
最佳实践:限流和熔断的阈值应与 Error Budget 消耗速率联动。当 Budget 剩余不足 10% 时,自动降低限流阈值并缩短熔断冷却时间,优先保护剩余预算不被异常流量耗尽。

4.4 错误码定义

统一的错误码体系让客户端能够精确判断错误类型并采取对应策略。Error Budget API 采用三段式错误码:HTTP 状态码 + 业务码 + 描述信息。

HTTP 状态码 业务码 描述 客户端处理建议
400 EB_BAD_REQUEST 请求参数校验失败 检查请求体字段
401 EB_UNAUTHORIZED 认证失败或 无效 刷新令牌
403 EB_FORBIDDEN 无权限操作该服务的 Budget 联系管理员授权
404 EB_SERVICE_NOT_FOUND 指定的服务未注册 检查服务名
409 EB_CONFLICT 版本冲突或预算状态异常 重新获取最新状态后重试
429 EB_RATE_LIMITED 请求频率超限 等待 Retry-After 后重试
503 EB_SERVICE_UNAVAILABLE 熔断器打开或后端不可用 指数退避重试
// 错误响应体 JSON 格式
{
  "error": {
    "code": "EB_RATE_LIMITED",
    "message": "请求频率超过服务级限流阈值",
    "details": {
      "limit": 100,
      "current": 101,
      "reset_at": "2025-03-15T10:00:00Z"
    },
    "request_id": "req-abc123"
  }
}
设计要点:
  • 每个错误响应必须包含 request_id,便于链路追踪。
  • 429 和 503 错误必须附带 Retry-After 或 reset_at 字段,指导客户端重试时机。
  • 业务码使用大写字母 + 下划线,前缀 EB_ 标识 Error Budget 域。

4.5 综合架构示意

下图展示 Error Budget API 在变更窗口场景中的完整调用链路,涵盖限流、幂等校验、熔断和错误码返回。

Error Budget API 调用链路 客户端 CI/CD / 变更工具 限流层 令牌桶 / 滑动窗口 幂等校验 Idempotency-Key 熔断器 状态机 后端服务(Budget 引擎) 消耗 / 恢复 / 查询 错误码 & 响应体 EB_xxx + request_id 说明:请求依次经过限流、幂等校验、熔断器,到达后端引擎;任何一层拒绝都会直接返回标准错误码响应体,不继续向后传递。
实战要点:在变更窗口的 consume 和 restore 接口中,幂等校验应优先于限流执行,避免因限流丢弃幂等重试导致客户端误判。熔断器打开时,限流层应直接返回 503,不再消耗令牌。