GitHub 这次 7 小时 47 分钟事故,最值得抄进自己系统的不是“多加机器”,而是先把 Retry Loop 关进笼子
GitHub 昨天公布了 8 月 17 日事故复盘。
这次事故持续 7 小时 47 分钟,影响了 github.com、认证、GitHub Actions、API、Pull Request、Issue 和 Copilot。
表面看,这是一个很典型的容量事故:Central US 数据中心里的关键基础设施组件,在新的流量峰值下没有及时扩容,压力随后扩散,认证和多个服务一起受到影响。
真正让我觉得特别值得 AI 工程团队看的,是恢复阶段的另一个细节:
部分 Copilot 服务在恢复时出现了客户端 Retry Loop,错误请求持续重试,反过来继续增加恢复阶段的流量。
也就是说,原始故障还没完全消失,客户端又制造了一轮“自激流量”。
Agent 系统尤其容易踩这个坑,因为它天然比普通 Web 服务有更多重试层。
一次“善意重试”为什么会变成二次故障
正常状态:
1000 req/s
如果下游突然有 40% 请求超时,而每个失败请求最多重试两次:
原始请求:1000
第一轮失败:400
第一轮重试:400
其中再次失败:160
第二轮重试:160
系统瞬间已经接近:
1560 req/s
如果下游本来就是因为容量不够才失败,这些请求不是“恢复机制”,而是继续把剩余容量挤掉。
更危险的是,生产系统里重试很少只有一层:
SDK Retry
业务 Retry
消息队列 Retry
Agent Step Retry
用户手动重试
五层叠在一起,一个请求很容易被放大十几次。
我现在会给 Retry 单独做预算
只写:
retry:
max-attempts: 3
不够。
我更愿意加:
retry:
max-attempts: 2
retry-budget-ratio: 0.08
backoff: exponential
jitter: true
max-attempts 控制的是单个请求。
retry-budget-ratio 控制的是整个系统在一个时间窗口内,额外重试流量不能超过正常请求的 8%。
这是两个完全不同的问题。
十万个请求同时失败时,前者几乎救不了你,后者才开始有价值。
Agent 还有一个普通 Web 服务没有的放大器:Loop
一个用户请求可能长这样:
User
↓
Router
↓
Planner
↓
RAG
↓
Tool A
↓
Tool B
↓
Reviewer
↓
Final Model
表面上是:
100 req/s
内部可能变成:
700—1500 次模型和 Tool 调用
某个 Prompt 一改,Reviewer 从两轮变成八轮,用户 QPS 没变,内部负载却直接翻几倍。
所以我越来越建议监控:
model_calls_per_run
tool_calls_per_run
steps_per_run
retry_per_run
而不是只看入口 API QPS。
一个很有用的指标:Amplification Factor
定义:
内部调用总数
/
用户请求数
例如:
1 万次用户请求
→ 7.8 万次模型调用
→ 3.2 万次 Tool Call
模型放大系数:
7.8×
Tool 放大系数:
3.2×
如果一个新版本上线后,模型放大从 7.8× 变成 12.4×,即使用户没涨,基础设施也可能突然过载。
这个指标特别适合发现“Agent 变得更啰嗦、更喜欢循环”的问题。
GitHub 这次的增长数字也很值得看
GitHub 自己披露,从 4 月到现在,月 Commit 已经从:
14 亿
增长到:
29 亿
接近翻倍。
GitHub 同时明确说,这能解释压力,但不是事故的借口。
我很喜欢这句话。
很多系统出问题后的第一反应是:
“最近用户涨太快。”
可容量规划的职责本来就是应对增长。
真正应该问的是:
关键组件为什么没有提前扩容?
哪一个组件不能水平扩展?
Capacity Forecast 为什么没看到拐点?
AI 应用更容易低估真实容量
因为容量单位不能只用 QPS。
还需要:
Token / sec
Tool Calls / sec
Concurrent Runs
Queue Depth
Context Size
Retry Rate
Fan-out
两个同样 100 QPS 的 Agent:
A:
每个请求 1 次模型调用
B:
每个请求 9 次模型调用
完全不是一个容量等级。
恢复阶段不要瞬间切回 100%
GitHub 的恢复方式包括:
Reroute Traffic
Isolate Infrastructure
Restore in Stages
我觉得“Restore in Stages”特别重要。
AI Provider 恢复以后,不要:
0% → 100%
更合理:
5%
↓
15%
↓
30%
↓
60%
↓
100%
每一阶段观察:
Error Rate
P95
429
Queue Depth
Retry Rate
健康检查变绿,不代表系统已经能吃满全部积压流量。
为什么恢复阶段比正常阶段更容易过载
故障一小时以后,系统会积累:
- 消息队列;
- Scheduled Task;
- 用户手动重试;
- Webhook;
- Batch;
- Cache Miss;
- 延迟任务。
服务一恢复:
Backlog
+
正常新流量
一起冲进来。
所以恢复阶段通常需要专门的:
Queue Drain Rate
例如:
recovery:
normal-workers: 100
recovery-workers: 130
max-queue-drain-qps: 1200
只比正常速度高一点,慢慢排空。
否则恢复动作本身会变成第二次压测。
GitHub 已经加了很多资源,但“加机器”并不是全部答案
GitHub 说,今年已经增加超过:
300 万 CPU Cores
120 PB High-speed Storage
同时加速向 Azure 迁移。
当前 Azure 已承载大约:
58% GitHub 平台负载
50% Git 操作
而 5 月平台负载还只有 12%。
这已经是巨大的基础设施扩展。
但 GitHub 仍然强调要继续消除:
architectural bottlenecks
原因很简单。
一个全局锁、单一 Metadata Service、集中认证依赖,再多机器也不一定解决。
Agent 平台也很容易造出全局瓶颈
典型的:
单一 Tool Registry
单一 Approval Service
单一 Budget DB
单一 Session Store
单一 Prompt Config Service
每个 Run 都经过它。
平时看起来很稳定,一到流量峰值就成为整个系统的共享故障点。
这些 Control Plane 组件同样需要:
缓存
分区
只读副本
降级策略
Fail Open / Fail Closed 设计
Authentication 往往是最危险的共享依赖
GitHub 这次容量压力传播后,认证失败影响了多个服务。
企业 Agent 也一样。
如果每个 Tool Call 都要实时访问中央 Authorization Service,一旦授权服务 P95 从 20ms 涨到 3 秒:
所有 Agent Step 一起卡住
可以考虑:
Signed Capability Token
Short-lived Credential
短期 Authorization Cache
降低每一步都回中心服务的压力。
高风险撤权再用更严格的失效机制。
我会提前写一张 Degradation Matrix
不是所有依赖挂了都应该返回 500。
| 依赖故障 | 降级方式 |
|---|---|
| 强模型不可用 | 低风险任务切备用模型 |
| Vector DB 慢 | 减少 TopK 或关闭非关键 RAG |
| Judge 不可用 | 低风险继续,高风险暂停 |
| Analytics 挂 | 主业务继续 |
| Tool Registry 慢 | 使用短期缓存 |
| Approval 挂 | 高风险写操作暂停 |
| Audit 挂 | 高风险 Fail Closed |
事故发生时再临时决定,通常来不及。
最值得主动演练的是“故障越大,请求越多”
我会在测试环境直接制造:
Provider 50% timeout
然后观察:
客户端 QPS
SDK Retry
Server Retry
Queue Depth
模型调用量
最关键的问题不是“系统能不能重试成功”,而是:
失败 10 分钟以后,系统内部流量是下降了,还是上升了?
如果故障越严重,QPS 越高,说明 Retry 设计有问题。
Chaos Test 可以很简单
Scenario 1:
10% 503
Scenario 2:
30% Timeout
Scenario 3:
429 + Retry-After
Scenario 4:
Dependency Slowly Recovers
Scenario 5:
Queue Backlog + Provider Recovery
每个场景检查:
是否自动降载
是否触发 Circuit Breaker
是否限制 Retry
是否平滑恢复
Circuit Breaker 不要只看“连续失败次数”
Agent 调用本身可能很慢。
如果等:
连续 20 次失败
才熔断,也许已经过去几分钟。
更适合用:
滑动窗口错误率
Timeout Rate
429 Rate
P95
例如:
circuit-breaker:
window: 30s
minimum-calls: 50
open-if-error-rate: 0.35
open-if-timeout-rate: 0.20
最后一个我会从 GitHub 事故里带走的指标:Recovery Amplification
定义:
恢复阶段总请求量
/
同时间正常基线请求量
如果长期看到:
2.5×
3.2×
说明恢复阶段有大量 Retry、Backlog 或同步行为需要治理。
这次 GitHub 事故持续 7 小时 47 分钟,根因是容量。
但对 Agent 工程最有启发的细节,是那条:
Copilot client-side retry loop
increased traffic during recovery
Agent 系统天然比普通应用有更多重试、循环、Fan-out 和异步任务。
只要其中一个没有预算,故障就很容易自我放大。
所以现在我看一个生产 Agent 系统,除了问:
正常情况下能跑多少 QPS?
还会再问一句:
当下游已经坏了,你的系统会自动变安静,还是会更疯狂地请求它?
后一个问题往往更重要。
更多企业级 AI 应用、Agent、RAG 与模型工程化内容,我会继续整理在 智元界:
https://www.zyentor.com/