GitHub 稳定性崩塌:AI 流量 3.5 倍暴增与 squash merge 数据损坏的教训

2026-05-13 16 预计阅读时间:1 分钟
来源:oschina.net AI 摘要 原文链接

免责声明:本文为 AI 摘要整理,建议结合原文阅读。摘要可能省略上下文、版本差异或边界条件,不作为官方说明。

预计阅读时间:11 分钟

一个代码托管平台的可用性跌到 86%,意味着每个月有超过 4 天无法正常工作。更致命的是,2025 年 4 月 23 日的一次 squash merge bug 直接损坏了 2,092 个 PR 的提交记录——这不是"服务慢了一点",而是数据本身出了问题。资深工程师选择离职,信号已经很明确:当基础设施的信任基础动摇时,留在上面的人每天都在赌。

可用性 86% 到底有多糟糕

业界常说的"五个九"(99.999%)意味着全年停机不超过 5 分钟。99.9% 也还算能接受,全年约 8.7 小时。而 86% 意味着全年有超过 51 天处于不可用状态。对任何以 CI/CD 为命脉的团队来说,这不是 inconvenience,是 production outage。

GitHub 官方状态页过去几个月的红色条带密度明显增加,从 API 限流到 git push 失败再到 webhook 延迟,几乎每周都有新事件。The Pragmatic Engineer 的报道把根因指向了 AI 驱动的流量暴增——Copilot、AI agent、自动化工具链的调用量在短时间内翻了 3.5 倍,GitHub 的内部服务根本没做好这个量级的容量规划。

squash merge bug:数据完整性事故的细节

4 月 23 日的事故是最值得技术团队深挖的部分。squash merge 是 GitHub PR 合并的常见策略:把一个分支上的多个 commit 压成一个 commit 合入主分支,保持历史线性。但这次 bug 导致 squash 后生成的 commit 与原始 PR 的元数据关联断裂——2,092 个 PR 的提交记录被损坏,部分 commit SHA 失效,部分 PR 状态异常。

受影响方包括 Modal 等知名公司。这类事故的可怕之处在于:它不是"你看不到页面了",而是"你以为代码还在,但引用关系已经断了"。对于依赖 commit SHA 做 reproducible build、依赖 PR number 做 audit trail 的团队,这是根本性的信任破坏。

AI 流量 3.5 倍:基础设施没跟上需求曲线

Copilot 的代码补全、AI agent 的批量操作、CI 系统中嵌入的 LLM 调用——这些场景都在通过 GitHub API 产生请求。3.5 倍的增幅不是渐进式的增长,是阶跃函数。GitHub 的服务架构(大量依赖内部 monolith + MySQL + Redis 缓存层)在面对这种请求模式变化时,暴露了几个结构性问题:

  • 限流策略滞后:对 AI agent 的识别和分级限流没有及时上线,导致正常开发者流量被挤占。
  • 缓存命中率下降:AI 请求的模式和人类开发者不同(更频繁的批量读取、更少的重复路径),原有缓存策略失效。
  • 数据库连接池耗尽:squash merge 等写操作在排队,读请求又在暴增,连接池成了瓶颈。

这不是 GitHub 独有的问题。任何提供 API 的平台在 AI 时代都会面临类似的流量结构变化。

实操:排查你的仓库是否受影响 + 建立可用性监控

下面给出两个可以直接运行的脚本。第一个检查你的仓库在 4 月 23 日前后是否有异常的 squash merge 记录;第二个用 GitHub API 建立一个轻量的可用性监控。

检查受影响 PR 的脚本

#!/usr/bin/env bash
# check_squash_integrity.sh
# 检查指定仓库在 2025-04-20 ~ 2025-04-25 期间合并的 PR 是否存在异常
# 使用前需要设置 GH_TOKEN 和 REPO

set -euo pipefail

REPO="${REPO:-owner/repo}"       # 改成你的仓库,格式 owner/repo
START_DATE="2025-04-20"
END_DATE="2025-04-25"
GH_TOKEN="${GH_TOKEN:-}"         # 设置你的 GitHub token

if [ -z "$GH_TOKEN" ]; then
  echo "请设置 GH_TOKEN 环境变量"
  exit 1
fi

API="https://api.github.com/repos/${REPO}/pulls"

# 拉取指定时间范围内已合并的 PR
echo "=== 检查 ${REPO}${START_DATE} ~ ${END_DATE} 期间合并的 PR ==="

PR_LIST=$(curl -s -H "Authorization: token ${GH_TOKEN}" \
  "${API}?state=closed&per_page=100&sort=updated&direction=desc" \
  | jq -r --arg start "$START_DATE" --arg end "$END_DATE" \
    '.[] | select(.merged_at != null 
                  and .merged_at >= $start 
                  and .merged_at <= $end) 
     | .number')

SUSPECT_COUNT=0

for pr_num in $PR_LIST; do
  # 获取 PR 详情,检查 merge_commit_sha 是否有效
  pr_detail=$(curl -s -H "Authorization: token ${GH_TOKEN}" \
    "${API}/${pr_num}")

  merge_sha=$(echo "$pr_detail" | jq -r '.merge_commit_sha')
  merged_via=$(echo "$pr_detail" | jq -r '.merged_via // "unknown"')

  # 尝试在本地验证该 SHA 是否存在于主分支
  # 如果 merge_commit_sha 为 null 或在远程找不到,标记为可疑
  if [ "$merge_sha" = "null" ] || [ -z "$merge_sha" ]; then
    echo "[可疑] PR #${pr_num}: merge_commit_sha 为空,合并方式=${merged_via}"
    SUSPECT_COUNT=$((SUSPECT_COUNT + 1))
  else
    # 在远程检查该 commit 是否存在
    commit_check=$(curl -s -o /dev/null -w "%{http_code}" \
      -H "Authorization: token ${GH_TOKEN}" \
      "https://api.github.com/repos/${REPO}/commits/${merge_sha}")

    if [ "$commit_check" != "200" ]; then
      echo "[可疑] PR #${pr_num}: SHA ${merge_sha} 在远程不存在 (HTTP ${commit_check}),合并方式=${merged_via}"
      SUSPECT_COUNT=$((SUSPECT_COUNT + 1))
    fi
  fi
done

echo ""
echo "=== 总结:发现 ${SUSPECT_COUNT} 个可疑 PR ==="
if [ "$SUSPECT_COUNT" -gt 0 ]; then
  echo "建议:对这些 PR 重新检查代码完整性,必要时重新 squash merge"
fi

运行方式:

export GH_TOKEN="ghp_你的token"
export REPO="your-org/your-repo"
bash check_squash_integrity.sh

需要安装 jqcurl。如果 PR 数量超过 100,需要加分页逻辑或改用 gh CLI。

轻量可用性监控

"""
github_availability_monitor.py
每 5 分钟探测 GitHub API,记录可用性数据到本地 CSV。
适合小团队快速建立基线,不依赖外部监控服务。
"""

import csv, time, requests, datetime, os

# ---- 配置 ----
GITHUB_TOKEN = os.getenv("GH_TOKEN", "")  # 可选,有 token 限流更宽松
INTERVAL_SECONDS = 300                     # 5 分钟
CSV_FILE = "github_availability.csv"
ENDPOINTS = [
    ("api_root",   "https://api.github.com"),
    ("user_api",   "https://api.github.com/user"),
    ("git_push",   "https://github.com"),   # 基础可达性
]

def probe(name: str, url: str) -> dict:
    headers = {"Authorization": f"token {GITHUB_TOKEN}"} if GITHUB_TOKEN else {}
    try:
        r = requests.get(url, headers=headers, timeout=10)
        return {
            "timestamp": datetime.datetime.utcnow().isoformat(),
            "endpoint": name,
            "status_code": r.status_code,
            "latency_ms": round(r.elapsed.total_seconds() * 1000),
            "ok": r.status_code < 500,
        }
    except requests.RequestException as e:
        return {
            "timestamp": datetime.datetime.utcnow().isoformat(),
            "endpoint": name,
            "status_code": 0,
            "latency_ms": -1,
            "ok": False,
            "error": str(e),
        }

def main():
    with open(CSV_FILE, "a", newline="") as f:
        writer = csv.DictWriter(f, fieldnames=["timestamp", "endpoint", "status_code", "latency_ms", "ok", "error"])
        if f.tell() == 0:
            writer.writeheader()

        while True:
            for name, url in ENDPOINTS:
                row = probe(name, url)
                writer.writerow(row)
                f.flush()
                status = "✓" if row["ok"] else "✗"
                print(f"{row['timestamp']}  {name}: {status}  {row['latency_ms']}ms")
            print(f"--- 等待 {INTERVAL_SECONDS}s ---")
            time.sleep(INTERVAL_SECONDS)

if __name__ == "__main__":
    main()

运行后会在本地生成 github_availability.csv,你可以用任何工具做可视化。跑一周就能拿到自己的可用性基线数据,不再依赖 GitHub 自己的状态页。

这件事对依赖 GitHub 的团队意味着什么

短期:如果你在 4 月 20–25 日间有 squash merge 的 PR,跑一遍上面的检查脚本。发现可疑记录时,最安全的做法是重新创建分支、重新 squash merge,确保主分支上的 commit SHA 是有效的。对于依赖 commit SHA 做 hash 校验的构建系统(如 Go module、Docker layer cache),损坏的 SHA 会导致构建失败或缓存污染。

中期:建立自己的可用性监控。GitHub 状态页的更新往往滞后,而且不区分"API 可用但限流严重"和"完全不可用"。自己的探针数据才是真实 SLA。

架构层面:这次事故再次提醒——把所有关键路径绑在一个平台上是单点风险。考虑:

  • git 镜像:用 git remote add mirror 把仓库同步到 GitLab 或自建 Git 服务器,CI 可以 fallback 到镜像源。
  • CI 多后端:GitHub Actions 出问题时,关键 pipeline 能切换到其他 runner。
  • 数据完整性校验:在 CI 中加入 git fsck 步步,定期检查仓库对象完整性。

GitHub 仍然是最大的代码托管平台,但"大"不等于"稳"。AI 流量的阶跃增长还会继续,这次事故不是最后一次。做好准备,比抱怨更有价值。


相关推荐