4. 错误码分类体系:系统级错误码、业务级错误码、第三方依赖错误码、安全错误码

在 BFF 层落地错误码规范时,最核心的决策是建立一套可扩展、可归因的分类体系。错误码不能是扁平的数字列表,而必须按照错误的来源与性质进行分层。本章将错误码划分为四大类别:系统级、业务级、第三方依赖级和安全级,每一类对应不同的处理策略、监控指标与告警阈值。

设计原则:错误码分类的核心目标是“快速定位责任方”。一个错误发生时,运维、开发、业务运营应能通过错误码前缀立即判断:是 BFF 自身故障、业务逻辑异常、下游服务不可用,还是安全攻击。

4.1 分类总览与编码结构

推荐采用 “字母前缀 + 数字分段” 的编码方式,使分类信息直接编码在错误码字符串中。以下为通用编码结构:

错误类别 前缀 数字范围 示例 责任方
系统级错误 SYS 1000-1999 SYS-1001 BFF 基础设施 / 平台
业务级错误 BIZ 2000-2999 BIZ-2003 业务产品 / 运营
第三方依赖错误 DEP 3000-3999 DEP-3012 下游服务 / 外部 API
安全错误码 SEC 4000-4999 SEC-4005 安全 / 风控

这种编码结构在日志聚合、监控告警和 API 响应体中都能快速过滤。例如,在 Grafana 中通过 error_code =~ "SYS-.*" 即可筛选所有系统级故障。

错误码分类体系架构 BFF 错误码分类 SYS 系统级 BIZ 业务级 DEP 依赖级 SEC 安全级 数据库连接失败 内存溢出 请求超时 参数校验失败 资源不存在 状态冲突 下游超时 下游限流 数据格式异常 Token 过期 权限不足 请求伪造

4.2 系统级错误码(SYS)

系统级错误码表示 BFF 层自身基础设施或运行环境出现故障。这类错误通常需要运维或平台团队介入处理,与业务逻辑无关。典型场景包括:

  • 连接资源失败:Redis 连接池耗尽、数据库连接超时、消息队列不可用。
  • 内部处理异常:JSON 序列化/反序列化失败、模板渲染错误、文件读写异常。
  • 资源限制:请求体超过大小限制、并发数超过线程池阈值、内存分配失败。
  • 配置错误:关键配置项缺失、环境变量未设置、路由规则解析失败。
监控策略:系统级错误应触发 P0/P1 级告警,直接通知值班运维。建议在 BFF 的全局异常过滤器中对 SYS 前缀的错误进行统一捕获,并记录完整的堆栈信息。
// 系统级错误码枚举示例(TypeScript)
export enum SysErrorCode {
  DB_CONNECTION_FAILED = 'SYS-1001',
  REDIS_POOL_EXHAUSTED = 'SYS-1002',
  REQUEST_BODY_TOO_LARGE = 'SYS-1003',
  INTERNAL_SERIALIZE_ERROR = 'SYS-1004',
  CONFIG_MISSING = 'SYS-1005',
}

4.3 业务级错误码(BIZ)

业务级错误码对应业务规则校验失败或用户操作不符合预期。这类错误是 BFF 层最常处理的类型,需要向前端返回友好的提示信息,且不应触发运维告警。

子类 错误码范围 典型场景 HTTP 状态码建议
参数校验 BIZ-2000 ~ BIZ-2049 邮箱格式错误、手机号不合法、必填字段缺失 400
资源状态 BIZ-2050 ~ BIZ-2099 订单已取消、商品已下架、用户已冻结 409
权限业务 BIZ-2100 ~ BIZ-2149 非本人操作、超出配额、等级不足 403
流程冲突 BIZ-2150 ~ BIZ-2199 重复提交、状态机跳转非法、并发更新 409
避坑提示:业务级错误码不要包含敏感信息(如用户身份证号、内部订单 ID 的完整值)。错误消息应面向用户可读,但错误码本身用于程序化处理,两者应分离。

4.4 第三方依赖错误码(DEP)

BFF 作为聚合层,高度依赖下游微服务或外部 API。第三方依赖错误码专门用于标识下游服务返回的错误,帮助快速区分“BFF 自身问题”与“下游问题”。

DEP 错误码的设计要点:

  • 透传 vs 映射:对于下游返回的错误码,BFF 可以选择直接透传(如 DEP-3000 + 原始错误码),也可以映射为统一的 BFF 错误码。
  • 熔断与降级:当 DEP 错误码连续出现时,应触发熔断器打开,避免雪崩。
  • 超时与重试:DEP-3010 表示下游超时,BFF 应记录重试次数和耗时。
// 第三方依赖错误码映射示例
public class DepErrorMapper {
  private static final Map<String, String> MAPPING = Map.of(
    "USER_SERVICE_TIMEOUT", "DEP-3010",
    "ORDER_SERVICE_UNAVAILABLE", "DEP-3020",
    "PAYMENT_SERVICE_INVALID_RESPONSE", "DEP-3030"
  );

  public static String map(String downstreamCode) {
    return MAPPING.getOrDefault(downstreamCode, "DEP-3999");
  }
}

4.5 安全错误码(SEC)

安全错误码覆盖认证、授权、防篡改、防重放等安全相关场景。这类错误需要与安全风控系统联动,且通常需要记录详细的审计日志。

错误码 含义 触发条件 处理动作
SEC-4001 Token 无效或过期 JWT 签名验证失败、Token 已过期 返回 401,清除客户端 Token
SEC-4002 权限不足 用户角色不满足接口要求 返回 403,记录越权日志
SEC-4003 请求重放攻击 Nonce 重复或时间戳偏差过大 拒绝请求,触发风控告警
SEC-4004 参数篡改 签名校验失败、请求体被修改 返回 400,记录攻击来源 IP
SEC-4005 频率超限 单位时间内请求次数超过阈值 返回 429,触发限流
审计要求:所有 SEC 错误码必须记录完整的请求上下文(IP、User-Agent、请求路径、用户 ID),并写入独立的审计日志文件或发送到安全事件中心。

4.6 分类体系在异常处理框架中的落地

在 BFF 的异常处理框架中,错误码分类直接决定了异常类的继承结构和处理器的路由逻辑。以下是一个基于分类的异常类层次设计:

基于错误码分类的异常类层次 BffBaseException SysException BizException DepException SecException SysExceptionHandler BizExceptionHandler DepExceptionHandler SecExceptionHandler 统一响应体:{ code, message, category, timestamp, requestId }

通过这种分类体系,BFF 的异常处理框架可以实现:

  • 差异化处理:系统级异常自动触发告警和熔断;业务级异常仅返回提示;依赖级异常触发重试或降级;安全级异常记录审计日志。
  • 统一响应格式:所有异常最终输出为包含 category 字段的 JSON 响应,前端可根据分类决定是否展示错误详情。
  • 监控聚合:在 Prometheus 中按 category 标签聚合错误率,设置不同的告警阈值。
最佳实践:在 BFF 的全局异常过滤器中,通过 instanceof 判断异常所属分类,然后路由到对应的处理器。每个处理器只关注自己分类的错误码映射和响应格式,职责单一。