Appearance
下游故障后怎么继续服务: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 / 失败回 OPENRetry 仍然是单个 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 → OPENGraceful Degradation 是 breaker 打开后“系统还能提供什么”。例如检索服务不可用时,普通问答可以退化为只使用当前 Context;但“必须基于企业知识库给出带引用答案”的任务应该明确失败,而不是偷偷生成无依据回答。
因此降级策略必须绑定任务语义:可省略的增强能力可以降级,决定 correctness / safety 的依赖不能静默绕过。
Failure Modes
Circuit Open 后仍让普通请求探测下游
症状: 断路器只写日志,没有阻止流量继续调用故障依赖。
为什么危险: 故障被放大、恢复更慢。
处理: 维护 CLOSED/OPEN/HALF OPEN 与 probe budget,OPEN 快速 fail/degrade。
如何验证
| Case | 断言 |
|---|---|
| Circuit Open 后仍让普通请求探测下游 | 连续失败触发 OPEN,普通请求不再到达下游,只有受限 probe。 |
自测
- 下游持续失败时,为什么每个请求都继续 timeout+retry 比快速打开 circuit 更糟?
- Circuit open 后系统是直接失败还是降级服务,取决于什么业务 contract?给一个可以降级和一个不能降级的例子。