Skip to content
预计 1 分钟右侧目录可快速定位

下游故障后怎么继续服务:Circuit Breaker 与 Graceful Degradation ​

前置:如何限制重复和过载:Dedup、Rate Limit 与 Concurrency Limit
核心问题:下游持续失败时,什么时候应该停止调用并进入降级,怎样避免降级结果被误记成正常成功?

第三方搜索服务持续 503 时,如果每个 Run 仍然照常进入 timeout/retry,下游故障会转化为本系统的连接占用、队列堆积和延迟放大。这里要解决两个不同问题:什么时候停止把普通流量送给故障依赖,以及依赖不可用时系统还能提供什么。真正需要人做决策的场景留到下一篇 Human Control。

Circuit Breaker ​

Circuit Breaker 保护的是整个下游依赖,不是某一次请求。

text
CLOSED    正常放流量
→ failure rate 持续过高
OPEN      快速失败,不再继续压下游
→ cooldown
HALF_OPEN 少量 probe
→ 成功恢复 CLOSED / 失败回 OPEN

Retry 仍然是单个 operation 的恢复策略;Breaker 则在“这个服务整体明显坏了”时阻止成百上千个请求继续重试,把故障放大。

Graceful Degradation ​

Graceful Degradation 不是“出错以后随便返回点东西”,而是明确选择一个能力更弱、但仍有业务价值的路径。

例如主 Retrieval Provider 持续失败:

text
normal: hybrid retrieval + rerank
breaker OPEN
→ fallback to cached/local keyword index
→ result.status = DEGRADED
→ reason = primary_retriever_unavailable

关键是上层必须知道“少了什么”。如果降级结果被伪装成完整成功,后续 Agent 可能在证据不足时继续做高风险决策。

Circuit Breaker 决定“暂时不要再打这个依赖”,Degradation 决定“那现在还能提供什么”。

Circuit Breaker 不是“失败几次就永远关掉” ​

假设检索服务持续 503。没有 breaker 时,100 个 Run 都会继续打过去、超时、retry,形成放大流量。Breaker 可以经历:

text
CLOSED
  ↓ failures exceed threshold
OPEN       → 快速失败,不再把请求压向故障下游
  ↓ cooldown
HALF_OPEN  → 只放少量 probe
  ├─ success → CLOSED
  └─ failure → OPEN

Graceful Degradation 是 breaker 打开后“系统还能提供什么”。例如检索服务不可用时,普通问答可以退化为只使用当前 Context;但“必须基于企业知识库给出带引用答案”的任务应该明确失败,而不是偷偷生成无依据回答。

因此降级策略必须绑定任务语义:可省略的增强能力可以降级,决定 correctness / safety 的依赖不能静默绕过。

Failure Modes ​

Circuit Open 后仍让普通请求探测下游 ​

症状: 断路器只写日志,没有阻止流量继续调用故障依赖。

为什么危险: 故障被放大、恢复更慢。

处理: 维护 CLOSED/OPEN/HALF OPEN 与 probe budget,OPEN 快速 fail/degrade。

如何验证 ​

Case断言
Circuit Open 后仍让普通请求探测下游连续失败触发 OPEN,普通请求不再到达下游,只有受限 probe。

自测 ​

  1. 下游持续失败时,为什么每个请求都继续 timeout+retry 比快速打开 circuit 更糟?
  2. Circuit open 后系统是直接失败还是降级服务,取决于什么业务 contract?给一个可以降级和一个不能降级的例子。

Sources ​

AI Engineering · Agent · Harness · Backend Systems