3. 错误码设计原则:HTTP状态码与业务错误码、错误码分类(系统级/业务级/缓存级)、错误码可读性与可扩展性
在契约测试中,Redis缓存失效场景的错误码设计直接决定了服务间故障定位的效率与自动化恢复能力。一套优秀的错误码体系需要同时满足协议兼容性、语义清晰性和长期演进性三个维度。本章从HTTP状态码与业务错误码的协同关系出发,建立系统级/业务级/缓存级三级分类,并给出可读性与可扩展性的具体设计规则。
3.1 HTTP状态码与业务错误码的协同关系
HTTP状态码用于表达传输层语义,业务错误码用于表达应用层语义。两者必须协同工作,不能互相替代。在Redis缓存失效场景中,常见的组合如下:
| 场景 | HTTP状态码 | 业务错误码 | 说明 |
|---|---|---|---|
| 缓存Key不存在 | 200 OK | CACHE_MISS | 业务正常,仅缓存未命中 |
| 缓存数据格式异常 | 200 OK | CACHE_FORMAT_ERROR | 数据可读但结构不匹配 |
| 缓存连接超时 | 503 Service Unavailable | CACHE_TIMEOUT | 基础设施故障,触发降级 |
| 缓存数据过期且回源失败 | 502 Bad Gateway | CACHE_STALE_WITH_BACKEND_FAIL | 缓存失效+后端不可用 |
| 请求参数导致缓存查询异常 | 400 Bad Request | CACHE_INVALID_PARAM | 客户端错误,需修正请求 |
契约测试要点:在Pact或Spring Cloud Contract中,必须同时验证HTTP状态码和业务错误码的联合响应。仅断言状态码200无法覆盖缓存数据格式异常等业务级错误。
3.2 错误码三级分类体系
将错误码划分为系统级、业务级和缓存级三个层次,每个层次独立编号,避免交叉污染。这种分类在契约测试中允许消费者按层级进行选择性断言。
3.3 错误码可读性设计原则
错误码的可读性直接影响开发者在契约测试和线上排障中的效率。遵循以下三条原则:
- 前缀语义化:使用英文单词缩写作为前缀,如
CACHE_、BIZ_、SYS_,一眼识别所属层级。 - 后缀描述化:使用下划线连接的英文短语描述具体问题,如
CACHE_KEY_NOT_FOUND、CACHE_SERIALIZE_FAILED。 - 禁止纯数字编号:纯数字错误码(如
10001)在契约测试中无法通过名称推断含义,增加维护成本。
推荐格式:
示例:
[层级前缀]_[模块]_[具体错误]示例:
CACHE_REDIS_CONNECTION_TIMEOUT、BIZ_SEARCH_PARAM_INVALID
3.4 错误码可扩展性设计原则
错误码体系必须支持向前兼容和增量扩展,避免因新增错误码导致契约测试断裂。核心规则如下:
| 原则 | 说明 | 契约测试影响 |
|---|---|---|
| 预留编号区间 | 每个层级预留20%的编号空间用于未来扩展 | 消费者契约无需因新增错误码而修改 |
| 禁止删除已发布错误码 | 已发布的错误码只能标记为deprecated,不可物理删除 |
旧契约仍可匹配,提供迁移窗口 |
| 错误码与版本绑定 | 每个错误码关联引入时的API版本号 | 契约测试可基于版本范围过滤错误码 |
| 枚举式定义 | 使用枚举类集中管理所有错误码,禁止散落在代码各处 | 契约测试可直接引用枚举常量,避免硬编码 |
3.5 契约测试中的错误码断言策略
在契约测试中,针对Redis缓存失效场景的错误码断言应遵循以下策略:
- 层级匹配:消费者契约只断言自己关心的错误码层级,不耦合其他层级的具体值。
- 通配符支持:允许使用前缀通配符匹配,如
CACHE_*匹配所有缓存级错误码。 - 错误码+消息双断言:同时验证错误码和错误消息的模板,确保语义完整。
常见陷阱:不要在契约测试中直接断言完整的错误消息字符串。错误消息可能因国际化或文案优化而变更,应使用正则模板或消息模板ID进行匹配。
3.6 错误码定义示例(Java枚举)
public enum CacheErrorCode {
// 缓存级错误码
CACHE_KEY_NOT_FOUND("CACHE-001", "缓存Key不存在"),
CACHE_FORMAT_ERROR("CACHE-002", "缓存数据格式异常"),
CACHE_SERIALIZE_FAILED("CACHE-003", "缓存序列化/反序列化失败"),
CACHE_CONNECTION_TIMEOUT("CACHE-004", "缓存连接超时"),
CACHE_STALE_DATA("CACHE-005", "缓存数据过期且回源失败"),
// 系统级错误码
SYS_REDIS_CLUSTER_DOWN("SYS-001", "Redis集群不可用"),
SYS_MEMORY_LIMIT("SYS-002", "缓存内存达到上限"),
// 业务级错误码
BIZ_INVALID_SEARCH_PARAM("BIZ-001", "搜索参数校验失败"),
BIZ_DATA_NOT_FOUND("BIZ-002", "业务数据不存在");
private final String code;
private final String message;
CacheErrorCode(String code, String message) {
this.code = code;
this.message = message;
}
public String getCode() { return code; }
public String getMessage() { return message; }
}
契约测试集成:在Pact文件中,使用枚举常量生成错误码,确保提供者和消费者使用同一份错误码定义。例如:
$.body.errorCode: "CACHE-001"。