2. API设计治理基础:RESTful与GraphQL设计原则,错误码规范,响应体结构标准化

在错误处理移植适配之前,必须建立统一的API设计治理基线。RESTful与GraphQL作为当前最主流的两种API范式,其设计原则、错误码规范与响应体结构直接影响错误信息的传递效率与可移植性。本章将系统梳理这两大范式的核心治理要素,为后续事务边界中的错误处理适配奠定基础。

2.1 RESTful设计原则与错误处理基线

RESTful API以资源为中心,通过HTTP动词表达操作意图。其错误处理的核心原则是:利用HTTP状态码表达语义,利用响应体传递细节。

2.1.1 HTTP状态码分层使用规范

类别 状态码 语义 典型场景
成功 200 / 201 / 204 请求已处理 GET返回200,POST创建返回201,DELETE成功返回204
客户端错误 400 / 401 / 403 / 404 / 409 / 422 请求无效或无法处理 参数校验失败(400),资源不存在(404),冲突(409),校验语义错误(422)
服务端错误 500 / 502 / 503 服务端异常 内部错误(500),网关超时(502),服务不可用(503)
治理要点:禁止将业务逻辑错误映射为200状态码。所有业务异常必须使用4xx或5xx状态码,确保客户端能够通过状态码快速判断请求结果类别。

2.1.2 RESTful响应体标准化结构

标准化的响应体结构是错误处理可移植的前提。推荐采用信封模式(Envelope Pattern),将数据与元数据分离:

// 成功响应
{
  "code": 0,
  "message": "success",
  "data": {
    "id": "usr_12345",
    "name": "张三",
    "email": "zhangsan@example.com"
  },
  "requestId": "req_abc123",
  "timestamp": 1712563200000
}

// 错误响应
{
  "code": 40001,
  "message": "参数校验失败",
  "data": null,
  "errors": [
    {
      "field": "email",
      "rule": "email_format",
      "message": "邮箱格式不正确"
    },
    {
      "field": "age",
      "rule": "range",
      "message": "年龄必须在18-120之间"
    }
  ],
  "requestId": "req_def456",
  "timestamp": 1712563201000
}
关键字段说明:
  • code:业务错误码,0表示成功,非0表示具体错误类型
  • message:人类可读的错误概要
  • errors:错误详情数组,支持多字段校验错误聚合
  • requestId:请求追踪标识,用于日志关联与问题定位

2.2 GraphQL设计原则与错误处理差异

GraphQL采用单一端点、按需查询的模式,其错误处理机制与RESTful存在显著差异。GraphQL规范要求:无论请求是否部分失败,始终返回200状态码,错误信息嵌入响应体的errors数组中。

2.2.1 GraphQL响应体结构

{
  "data": {
    "user": {
      "id": "usr_12345",
      "name": "张三",
      "orders": null
    }
  },
  "errors": [
    {
      "message": "无法获取用户订单列表",
      "locations": [{"line": 6, "column": 5}],
      "path": ["user", "orders"],
      "extensions": {
        "code": "ORDER_FETCH_ERROR",
        "service": "order-service",
        "timestamp": "2024-04-08T10:00:01Z"
      }
    }
  ]
}
字段 说明 治理要求
message 错误描述(必填) 必须清晰、无歧义,面向开发者
locations 错误在查询中的位置 自动生成,用于调试
path 错误字段的路径 帮助客户端定位失败字段
extensions 扩展信息(推荐) 必须包含业务错误码、服务标识、时间戳
移植适配注意:GraphQL的200+errors模式与RESTful的4xx/5xx模式在错误传递路径上完全不同。在事务边界中,必须设计统一的错误码映射层,将GraphQL的extensions.code与RESTful的code字段对齐,避免下游消费者因范式差异而解析失败。

2.3 统一错误码规范设计

错误码是跨范式移植适配的核心桥梁。无论采用RESTful还是GraphQL,错误码必须遵循统一的编码规则,确保在事务边界中能够被正确识别与转换。

2.3.1 错误码分层编码规则

错误码分层编码结构 服务标识 2位数字 错误类别 2位数字 具体错误 2位数字 示例:040201 04(用户服务) - 02(参数校验) - 01(邮箱格式错误) 编码规则:6位数字,前2位服务标识,中间2位错误类别,后2位具体错误 服务标识 00-99,错误类别 01-99,具体错误 01-99

2.3.2 错误类别定义表

错误类别码 类别名称 说明 HTTP映射
01 认证错误 身份验证失败、Token过期 401
02 参数校验错误 请求参数格式、范围、必填校验失败 400 / 422
03 资源错误 资源不存在、资源冲突 404 / 409
04 权限错误 无操作权限、角色不匹配 403
05 业务逻辑错误 业务规则违反、状态机异常 422 / 409
06 服务端错误 内部异常、依赖服务故障 500 / 502 / 503

2.4 响应体结构标准化对比

在事务边界中,RESTful与GraphQL的响应体结构需要统一抽象。下表展示了两者在关键维度上的对比及适配策略:

维度 RESTful GraphQL 适配策略
状态码 HTTP状态码(200/4xx/5xx) 始终200 统一提取业务错误码,忽略HTTP状态码差异
错误位置 响应体顶层errors数组 响应体errors数组 结构兼容,可直接映射
字段级错误 errors[].field + errors[].message errors[].path + errors[].message 统一转换为field+path双标识
扩展信息 自定义字段(如requestId) errors[].extensions 统一放入extensions命名空间
部分成功 不支持(全成功或全失败) 支持(data部分为null) 引入部分成功标记字段

2.5 范式适配架构图

在API治理层面,需要构建一个错误处理适配层,将RESTful与GraphQL的错误输出统一为内部标准格式,确保事务边界中的错误处理逻辑与前端范式解耦。

API错误处理适配层架构 RESTful API HTTP 4xx/5xx 信封响应体 GraphQL API 200 + errors[] extensions.code 错误处理适配层 错误码映射 / 结构转换 / 字段归一 统一错误标准格式 code + message + errors + extensions
适配层核心职责:
  1. 错误码映射:将RESTful的HTTP状态码+业务码、GraphQL的extensions.code统一映射为6位标准错误码
  2. 结构转换:将RESTful的errors[].field与GraphQL的errors[].path统一为field+path双字段
  3. 元数据注入:统一注入requestId、timestamp、serviceName等追踪字段
  4. 部分成功处理:对GraphQL的部分成功场景,生成统一的partialSuccess标记

2.6 治理基线检查清单

在进入事务边界错误处理移植适配之前,请确保以下治理基线已落实:

检查项 RESTful要求 GraphQL要求 验收标准
状态码使用 严格遵循4xx/5xx语义 始终返回200 无业务错误使用200状态码
响应体结构 信封模式(code+data+errors) data+errors+extensions 统一包含code、message、requestId
错误码规范 6位数字分层编码 extensions.code使用6位数字 错误码可跨范式映射
字段级错误 errors[].field errors[].path 适配层统一输出field+path
追踪标识 requestId extensions.requestId 所有响应包含唯一请求ID
常见治理陷阱:
  • 将业务错误(如余额不足)映射为500状态码——应使用422或409
  • GraphQL中遗漏extensions字段,导致下游无法获取业务错误码
  • 错误码编码不统一,RESTful使用4位码而GraphQL使用字符串码
  • 忽略部分成功场景,导致客户端无法区分全成功与部分成功