← 中文资源

简体中文版本

向依赖注入固定错误率

让假依赖按确定比例返回 500,断言重试上限、熔断与降级行为,而不是演变成全面故障或重试风暴。

阅读英文原文

概述

依赖完全宕机反而容易处理:熔断打开、流量停止,所有人都能理解。真正困难的是 30% 的请求失败,因为每个请求看起来都还有成功的可能。重试似乎合理,但在 30% 失败率下重试三次会把一次用户请求放大成四次上游调用,把已经吃力的服务彻底压垮。需要设计的是降级,而不是完美。

步骤

  1. 用取模计数让失败率精确且可复现:
let call = 0;
if (++call % 10 < 3) return res.writeHead(500).end('injected');
  1. 设置重试预算:每个用户请求最多两次上游调用,并加入抖动。
  2. 增加熔断器:
const breaker = new CircuitBreaker(search, {
  timeout: 1000,
  errorThresholdPercentage: 50,
  volumeThreshold: 10,
  resetTimeout: 5000,
});
  1. 熔断打开时返回降级结果:缓存数据、degraded: true 与 Warning 响应头,而不是把错误直接抛给用户。
  2. 关闭故障注入,等待 resetTimeout,确认探活成功后熔断器关闭。

验证

注入开始后,前十个请求中超过一半失败,熔断器应打开,后续请求立即拒绝而不是等待超时。降级响应应为 200 且带 degraded: true,错误率保持在 SLO 之内。关闭注入并等待 6 秒后,真实依赖恢复,熔断器回到关闭状态且无需重启。

注意事项

  • 随机注入会产生不稳定测试,应使用确定性序列。
  • 没有重试预算的熔断器仍会产生突发流量,必须先限制每请求的上游调用次数。
  • 写操作重试需要幂等键,超时不等于失败。
  • 熔断状态是进程级的,集群中可能部分实例打开、部分关闭。
  • 降级必须有正确的缓存或兜底数据,注入只能证明路径被执行,不能证明数据正确。