4. 错误(Errors)深度解析:错误率的计算方式、HTTP错误码分类、业务错误与系统错误的区分
错误(Errors)是 Golden Signals 中直接反映服务质量受损的信号。与延迟的渐进式劣化不同,错误通常意味着请求处理失败或返回了不符合预期的结果。本节将深入解析错误率的精确计算方式、HTTP 错误码的分类体系,以及业务错误与系统错误的本质区别。
4.1 错误率的计算方式
错误率并非简单的“失败请求数 / 总请求数”。在 SRE 实践中,需要根据不同的观测粒度定义分母和分子,以确保指标能够真实反映用户体验。
| 计算维度 | 分母(总请求数) | 分子(错误数) | 典型场景 |
|---|---|---|---|
| 全局错误率 | 所有进入系统的请求 | 所有返回 5xx、4xx(除特定豁免)的请求 | 整体服务健康度大盘 |
| 端点级错误率 | 特定 API 路径的请求数 | 该路径返回非 2xx/3xx 的请求数 | 精细化排查单接口故障 |
| 用户感知错误率 | 用户发起的有效会话请求 | 用户侧感知到的失败(含超时、网络中断) | 客户端埋点监控 |
| 滑动窗口错误率 | 过去 N 分钟内的请求总数 | 过去 N 分钟内的错误总数 | 实时告警与动态阈值 |
关键公式: 错误率(%)=(错误请求数 / 有效总请求数)× 100%。
注意: 分母应排除健康检查、爬虫等非用户流量,避免稀释错误率。
注意: 分母应排除健康检查、爬虫等非用户流量,避免稀释错误率。
4.2 HTTP 错误码分类与映射
HTTP 状态码是衡量 Web 服务错误最直接的信号。SRE 需要将状态码映射到具体的故障类型,以便快速定位根因。
- 1xx(信息性): 通常不计入错误率,如 101 Switching Protocols。
- 2xx(成功): 正常响应,不计入错误。
- 3xx(重定向): 通常视为成功,但需关注重定向链是否异常。
- 4xx(客户端错误):
- 400 Bad Request: 请求格式错误,通常由客户端触发。
- 401/403 Unauthorized/Forbidden: 鉴权失败,需区分是用户输入错误还是系统权限配置问题。
- 404 Not Found: 资源不存在,可能是客户端错误或服务端路由配置缺失。
- 429 Too Many Requests: 限流触发,属于服务端主动保护行为,应单独监控。
- 5xx(服务端错误):
- 500 Internal Server Error: 通用服务端故障,需结合日志分析。
- 502 Bad Gateway: 上游服务不可用,常见于网关与后端连接失败。
- 503 Service Unavailable: 服务过载或正在维护,通常与容量相关。
- 504 Gateway Timeout: 上游响应超时,需排查网络或后端处理能力。
避坑指南: 不要将所有 4xx 都视为系统错误。例如,用户输入错误的密码导致 401,属于业务预期内的错误,不应计入系统错误率。但 429 限流错误应纳入系统错误监控,因为它反映了容量瓶颈。
4.3 业务错误与系统错误的区分
这是错误信号设计中最容易被忽视的环节。系统错误(如 5xx)代表基础设施或代码缺陷,而业务错误(如“余额不足”、“商品已下架”)代表业务逻辑的预期反馈。两者必须分开度量。
4.4 错误信号设计最佳实践
- 分层定义错误率: 为系统错误和业务错误分别定义独立的 SLI 和 SLO。例如:系统错误率 < 0.1%,业务错误率 < 5%。
- 使用错误预算: 将系统错误消耗的错误预算与业务错误消耗的错误预算分开管理,避免业务逻辑变更影响基础设施稳定性评估。
- 精细化告警规则: 对 5xx 错误设置即时告警(如 1 分钟内错误率 > 1%);对 4xx 错误设置趋势告警(如 30 分钟内错误率持续上升)。
- 错误码标准化: 在 API 响应体中统一返回
error_code字段,便于自动化分类和聚合。
实战建议: 在日志系统中为业务错误和系统错误打上不同的标签(如
error_type: business 和 error_type: system),配合 Prometheus 的 label 进行多维聚合,可以快速生成错误分布热力图。
4.5 错误率计算代码示例
以下是一个基于 PromQL 的错误率计算示例,区分了系统错误和业务错误:
# 系统错误率(基于HTTP 5xx状态码)
rate(http_requests_total{status=~"5.."}[5m])
/
rate(http_requests_total[5m])
* 100
# 业务错误率(基于自定义业务错误码,假设业务错误码以 1000 开头)
rate(http_requests_total{error_code=~"1..."}[5m])
/
rate(http_requests_total[5m])
* 100
# 总错误率(系统错误 + 业务错误,排除健康检查)
(
rate(http_requests_total{status=~"5..", endpoint!="/health"}[5m])
+
rate(http_requests_total{error_code=~"1...", endpoint!="/health"}[5m])
)
/
rate(http_requests_total{endpoint!="/health"}[5m])
* 100