发生了什么
2026 年 4 月 4 日星期六,Bluesky 的 AppView 数据平面——为该社交应用提供读取服务的后端——开始记录诸如“failed to set post cache item: dial tcp: bind: address already in use”之类的错误。该数据平面严重依赖 memcached 来减轻主 Scylla 数据库的负载,而值班的基础设施工程师 Jim Calabro 发现日志峰值与用户侧流量的下降相对应。网络监控一切正常,因此在整个周末服务蹒跚运行期间,原因始终未被发现。
根本原因是当周部署的一个新内部服务:每秒不到三次 GetPostRecord 请求,但每批包含 15,000–20,000 个帖子 URI(正常为 1 到 50 个)。每个数据平面 RPC 处理程序都用 errgroup.SetLimit 限制并发——唯独这个端点缺少这一行。单次调用就产生了多达 20,000 个 goroutine,拨出大量 memcached 连接;一旦 1,000 个套接字的空闲池溢出,它们便堆积在 TCP TIME_WAIT 中,耗尽了所有临时端口。该客户端运行在一个数据中心,且没有按客户端划分的指标,各类缓存错误掩盖了罪魁祸首。
4 月 6 日星期一,情况演变为死亡螺旋:每秒数百万次 memcached 请求失败,Bluesky 的“记录每个错误”策略试图每秒执行数百万次阻塞式 write(2) 日志写入。阻塞系统调用的洪流将 Go 运行时从约 150 个 OS 线程推高到 1,500 个,使 GC 饥饿并陷入长时间的 stop-the-world 暂停。激进调优的 GOGC 和 GOMEMLIMIT 使数据平面周期性地 OOM 崩溃——运行约 30 分钟后宕机,如此反复。每次重启都加深了困境:TIME_WAIT 套接字使重启后的进程无法重建其 memcached 连接池。
周一的临时补救措施荒谬得令人捧腹:一个自定义拨号器,为每个出站连接随机选择一个 127.x.y.z 环回 IP,将 ip+port 空间扩展到已耗尽范围之外。这阻止了螺旋,直到周三团队才找到真正的根本原因并恢复了缺失的 SetLimit(50)。Calabro 的公开事后分析还承认了一次沟通失误:状态页面曾将问题归咎于第三方网络提供商,而“显然并非如此”。
代价是什么
2026 年 4 月 6 日,约八小时内,大约半数 Bluesky 用户经历了间歇性停机——这是该平台基础设施负责人在任期间最严重的一次故障
为什么会发生
有界并发是靠约定而非结构来保证的:每个处理程序都有 SetLimit,唯独一个没有,而单个无界端点就足以耗尽主机级资源。
流量契约没有形状限制:没有任何机制拒绝 20,000 项的批次,因此一个安静的内部客户端——每秒 3 次请求——作为负载来源压过了数百万正常请求。
故障处理放大了故障:每秒数百万次错误地记录每个 memcached 错误,将缓存问题转化为线程爆炸、GC 暂停和 OOM 崩溃。
可观测性假设请求很小,且没有按客户端划分的指标,因此来自每种缓存类型的错误在数天内掩盖了唯一应负责的调用方和端点。
以重启作为恢复手段是行不通的:已死进程留下的 TIME_WAIT 套接字阻止新进程重建其 memcached 连接池,使 OOM 重启变成更多的端口耗尽。
教训
一个无界的 goroutine 循环压过了所有其他保障措施。并发限制必须是结构性的,而不是每个端点的习惯:唯一缺少限制的那个端点成了整个事故的根源。
后续
服务在周一通过随机环回拨号器稳定下来,该拨号器在真正的修复——恢复并发限制——于 4 月 8 日星期三落地后被移除。总暴露时间约为八小时,期间约半数用户经历间歇性停机。这份于 2026 年 4 月 10 日发布的事后分析承诺提供按客户端划分的可观测性、检测发送少量超大请求的客户端,并从高容量日志转向 Prometheus 指标和 OpenTelemetry 追踪;两天后,可靠性研究员 Lorin Hochstein 对其进行了详细的独立分析。
从这里,追溯依据
参考来源
- April 2026 Outage Post-Mortem Jim Calabro (Bluesky infrastructure engineer), pckt.blog · pckt.blog ·
- Thoughts on the Bluesky public incident write-up Surfing Complexity (Lorin Hochstein) · surfingcomplexity.blog ·
- Bluesky April 2026 Outage Post-Mortem (discussion, 141 points) Hacker News · news.ycombinator.com ·