← 中文资源

简体中文版本

熔断器

熔断器在依赖连续失败超过阈值后停止发送请求,快速失败并给依赖恢复空间,避免调用方被超时耗尽。

阅读英文原文

为什么快速失败有帮助

当依赖挂起时,调用方等待超时,线程或连接池被占满,故障扩散到健康路径。熔断器把反复的慢失败转换为本地快速失败,调用方可以降级、返回缓存或清晰错误,而不再消耗更多资源。

状态机

type State = 'closed' | 'open' | 'half-open';

class CircuitBreaker {
  private state: State = 'closed';
  private failures = 0;
  private openedAt = 0;

  constructor(
    private readonly threshold = 5,
    private readonly cooldownMs = 30_000,
  ) {}

  async call<T>(operation: () => Promise<T>): Promise<T> {
    if (this.state === 'open') {
      if (Date.now() - this.openedAt < this.cooldownMs) {
        throw new Error('circuit open');
      }
      this.state = 'half-open';
    }
    try {
      const result = await operation();
      this.failures = 0;
      this.state = 'closed';
      return result;
    } catch (error) {
      this.failures += 1;
      if (this.state === 'half-open' || this.failures >= this.threshold) {
        this.state = 'open';
        this.openedAt = Date.now();
      }
      throw error;
    }
  }
}

选择阈值

阈值应反映依赖的正常错误率和调用方的容忍度。只统计基础设施失败,不统计校验错误。使用滚动窗口或连续失败计数,并让冷却时间足够依赖恢复,又足够短以检测恢复。

何时使用

在具有部分失败模式的远程依赖上使用熔断器:支付提供商、搜索服务、遗留 API。与重试策略相比,熔断器在故障期间减少负载,而重试增加负载;应组合使用,使重试只发生在熔断器关闭时。与限流相比,熔断器对失败作出反应,而不是对流量大小。

陷阱

永久打开的熔断器会阻断所有流量;必须定义半开探测。每个主机一个熔断器可能掩盖区域故障;每个依赖一个熔断器可能因单个坏实例过度跳闸。应记录状态转换和失败原因,帮助运维区分真实故障与阈值配置错误。

相关资源