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-.*" 即可筛选所有系统级故障。
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 的异常处理框架中,错误码分类直接决定了异常类的继承结构和处理器的路由逻辑。以下是一个基于分类的异常类层次设计:
通过这种分类体系,BFF 的异常处理框架可以实现:
- 差异化处理:系统级异常自动触发告警和熔断;业务级异常仅返回提示;依赖级异常触发重试或降级;安全级异常记录审计日志。
- 统一响应格式:所有异常最终输出为包含
category字段的 JSON 响应,前端可根据分类决定是否展示错误详情。 - 监控聚合:在 Prometheus 中按
category标签聚合错误率,设置不同的告警阈值。
最佳实践:在 BFF 的全局异常过滤器中,通过
instanceof 判断异常所属分类,然后路由到对应的处理器。每个处理器只关注自己分类的错误码映射和响应格式,职责单一。