4、统一错误码体系设计:租户级、服务级、系统级错误码分层规范

在多租户 SaaS 鉴权拦截链路中,错误码的混乱是导致故障定位慢、熔断策略误判、租户隔离失效的首要原因。本章定义一套三层错误码分层规范,将错误码按影响范围划分为租户级、服务级、系统级,并给出编码规则、分段定义与熔断映射关系。

核心原则:错误码必须携带“层级标识”,让熔断降级组件在不解码业务语义的情况下,直接根据错误码前缀判断是否触发租户级熔断、服务级降级或系统级告警。

4.1 三层错误码架构总览

下图展示了错误码在鉴权拦截链路中的分层归属与传递路径:

三层错误码分层架构 系统级 (SYS-xxx) 影响所有租户 · 基础设施故障 · 全局熔断 示例:SYS-001 缓存集群不可用、SYS-002 数据库连接池耗尽 服务级 (SRV-xxx) 影响单个微服务实例 · 触发服务降级 · 不影响其他服务 示例:SRV-101 鉴权服务超时、SRV-202 Token 解析服务限流 租户级 (TNT-xxx) 影响单个租户 · 触发租户级熔断 · 其他租户正常服务 示例:TNT-301 租户配额超限、TNT-302 租户密钥已吊销 错误码向上传递时,熔断组件根据层级前缀自动匹配熔断策略,无需解析业务字段

4.2 错误码编码规范

错误码采用 层级前缀 + 数字分段 的固定格式,共 7 位字符:

格式:[层级前缀]-[三位数字]
层级前缀:TNT(租户级) | SRV(服务级) | SYS(系统级)
示例:TNT-301、SRV-101、SYS-001
层级 前缀 数字范围 熔断行为 恢复方式
租户级 TNT 300-399 租户级熔断(仅熔断该租户请求) 租户配置变更 / 配额释放后自动恢复
服务级 SRV 100-299 服务降级(返回降级响应,不熔断租户) 服务健康检查通过 / 限流窗口重置后恢复
系统级 SYS 001-099 全局熔断(所有租户请求降级或拒绝) 人工介入 / 基础设施恢复后手动解除
设计要点:数字分段预留了扩展空间。例如服务级 100-199 为鉴权链路专用错误码,200-299 为其他通用服务错误码。租户级 300-349 为配额类错误,350-399 为安全策略类错误。

4.3 鉴权拦截链路错误码明细

针对鉴权拦截链路的核心节点,定义以下标准化错误码:

错误码 层级 含义 触发条件 熔断策略
SYS-001 系统级 缓存集群不可用 Redis/Memcached 连接失败 全局熔断 30s
SYS-002 系统级 数据库连接池耗尽 连接池活跃数达上限 全局熔断 60s
SRV-101 服务级 鉴权服务超时 鉴权请求超过 500ms 阈值 服务降级(返回缓存鉴权结果)
SRV-102 服务级 Token 解析失败 JWT 签名验证异常 服务降级(返回 401 并记录)
SRV-201 服务级 限流器触发 服务 QPS 超过阈值 服务降级(返回 429 限流响应)
TNT-301 租户级 租户 API 配额超限 租户日调用量超过购买配额 租户级熔断(仅该租户请求返回 403)
TNT-302 租户级 租户密钥已吊销 租户主动吊销或过期 租户级熔断(立即拒绝)
TNT-303 租户级 租户并发超限 租户并发连接数超过上限 租户级熔断(等待并发释放)

4.4 错误码与熔断降级的映射关系

熔断降级组件通过错误码前缀自动匹配熔断策略,无需硬编码业务逻辑:

// 伪代码:熔断决策引擎
function decideCircuitBreaker(errorCode, tenantId) {
    if (errorCode.startsWith("SYS-")) {
        return globalCircuitBreaker.trip();          // 全局熔断
    } else if (errorCode.startsWith("SRV-")) {
        return serviceDegrader.degrade();            // 服务降级
    } else if (errorCode.startsWith("TNT-")) {
        return tenantCircuitBreaker.trip(tenantId);  // 租户级熔断
    } else {
        return unknownErrorHandler(errorCode);
    }
}
避坑指南:禁止在错误码中嵌入租户 ID、IP 等动态信息。错误码必须是静态枚举值,动态上下文(如租户 ID)应放在错误响应体的扩展字段中,否则会导致熔断策略无法按层级归类。

4.5 错误码传递与日志规范

错误码在鉴权拦截链路中必须透传,并在日志中按层级聚合:

  • 请求头透传:在 HTTP 响应头 X-Error-Code 中携带错误码,供网关和客户端识别。
  • 日志标签:日志输出时使用 [TNT]、[SRV]、[SYS] 标签,便于监控系统按层级告警。
  • 聚合指标:Prometheus 指标 saas_error_total{level="tenant", code="TNT-301"} 按层级和错误码聚合。
// 日志输出示例
2025-03-20 10:15:32 [ERROR] [TNT] [tenantId=acme-corp] TNT-301 租户API配额超限
2025-03-20 10:15:33 [WARN]  [SRV] [service=auth] SRV-101 鉴权服务超时,触发降级
2025-03-20 10:15:34 [CRIT] [SYS] [cluster=redis] SYS-001 缓存集群不可用,全局熔断

4.6 错误码扩展与版本管理

错误码体系需要支持版本化扩展,避免因新增错误码导致熔断策略混乱:

版本 变更内容 兼容性
v1.0 初始定义 8 个核心错误码 —
v1.1 新增 TNT-303 租户并发超限 向后兼容
v2.0 服务级错误码分段重构(100-199 鉴权专用) 需同步更新熔断映射表
最佳实践:将错误码枚举定义在独立模块中,通过配置中心下发。新增错误码时只需更新配置,无需重启服务。熔断决策引擎基于配置动态加载错误码与策略的映射关系。