4、统一错误码体系设计:租户级、服务级、系统级错误码分层规范
在多租户 SaaS 鉴权拦截链路中,错误码的混乱是导致故障定位慢、熔断策略误判、租户隔离失效的首要原因。本章定义一套三层错误码分层规范,将错误码按影响范围划分为租户级、服务级、系统级,并给出编码规则、分段定义与熔断映射关系。
核心原则:错误码必须携带“层级标识”,让熔断降级组件在不解码业务语义的情况下,直接根据错误码前缀判断是否触发租户级熔断、服务级降级或系统级告警。
4.1 三层错误码架构总览
下图展示了错误码在鉴权拦截链路中的分层归属与传递路径:
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 鉴权专用) | 需同步更新熔断映射表 |
最佳实践:将错误码枚举定义在独立模块中,通过配置中心下发。新增错误码时只需更新配置,无需重启服务。熔断决策引擎基于配置动态加载错误码与策略的映射关系。