2. 错误码设计原则:HTTP状态码类比、业务错误码分类、错误码与错误消息分离
在分布式系统与微服务架构中,错误码是服务间通信的“通用语言”。设计一套清晰、可扩展的错误码体系,能够显著降低排障成本、提升断言效率,并为发布回滚提供精确的触发信号。本节从三个核心维度展开:HTTP状态码类比、业务错误码分类、错误码与错误消息分离。
2.1 HTTP状态码类比:从传输层到业务层
HTTP状态码是业界最成熟的分层错误模型。将其设计哲学映射到业务错误码,可以快速建立团队共识:
| HTTP 状态码范围 | 语义 | 业务错误码类比 | 典型场景 |
|---|---|---|---|
| 2xx (成功) | 请求被正常处理 | 0 / 20000 系列 | 查询成功、操作完成 |
| 4xx (客户端错误) | 请求参数或权限问题 | 40000 系列 | 参数校验失败、鉴权过期 |
| 5xx (服务端错误) | 服务内部异常或依赖故障 | 50000 系列 | 数据库超时、下游服务不可用 |
设计建议:业务错误码不要直接复用 HTTP 状态码数字(如直接返回 400),而应使用独立编号体系。HTTP 状态码用于网关层,业务错误码用于应用层,两者互补而非替代。
2.2 业务错误码分类:三层结构
推荐采用 “模块 + 场景 + 具体错误” 的三层分类法,确保错误码具备可读性与可扩展性:
- 模块标识(2位):如 01=用户模块、02=搜索模块、03=订单模块。
- 场景标识(2位):如 01=参数校验、02=业务逻辑、03=依赖调用。
- 具体错误(2位):从 01 递增,表示该场景下的具体错误原因。
示例:020301 表示“搜索模块 - 依赖调用 - 索引服务超时”。
分类清单(以搜索服务为例):
- 20000 系列(成功):20000 = 成功,20001 = 部分命中。
- 40000 系列(客户端错误):40001 = 查询参数为空,40002 = 排序字段不合法,40003 = 分页越界。
- 50000 系列(服务端错误):50001 = 索引加载失败,50002 = 分词服务超时,50003 = 缓存穿透。
2.3 错误码与错误消息分离
这是生产级系统最容易忽略的设计。错误码是机器标识,错误消息是人类描述,两者必须解耦:
- 错误码:固定不变,用于日志聚合、告警规则、断言判断、发布回滚触发。
- 错误消息:可随版本迭代优化文案、支持国际化,不影响已有监控逻辑。
常见反模式:将错误消息直接拼入错误码字段(如返回
{"code": "PARAM_ERROR: 用户名不能为空"})。这会导致监控系统无法聚合、断言无法匹配、回滚策略失效。
推荐返回结构(JSON):
{
"code": 40001,
"message": "查询参数为空",
"detail": "搜索关键词长度不能少于2个字符",
"trace_id": "a1b2c3d4e5f6"
}
其中 code 用于断言与回滚决策,message 用于前端展示,detail 用于开发排障,trace_id 用于链路追踪。
2.4 错误码设计检查清单
| 检查项 | 通过标准 | 反例 |
|---|---|---|
| 唯一性 | 每个错误码全局唯一 | 不同模块共用 40001 |
| 可扩展 | 新增错误码不改变已有编号 | 重新编排整个序列 |
| 可读性 | 从编号可推断模块与场景 | 纯随机数字 |
| 消息分离 | code 与 message 为独立字段 | code 字段包含文案 |
| 断言友好 | 支持范围匹配(如 50000~59999) | 仅支持精确匹配 |
本节要点:
- 错误码设计应借鉴 HTTP 状态码的分层思想,但独立编号。
- 推荐“模块 + 场景 + 具体错误”的三层结构,便于自动化处理。
- 错误码与错误消息必须分离,这是发布回滚断言能够稳定工作的前提。