发生了什么
2018年2月3日至4日,《堡垒之夜:大逃杀》达到了340万同时在线玩家的峰值——而就在几个月前,此前的峰值仅为6万——那个周末变成了一场接连不断的宕机。Epic自己于2018年2月8日发布的复盘报告统计了六起不同的事件,其中既有部分服务中断,也有完全的服务中断。
最严重的故障出在MCP档案服务上,该服务由九个MongoDB分片支撑,每秒处理31.8万次读取和13.2万次写入。匹配分片开始将写入排队,使单次操作耗时飙升至4万毫秒以上,并阻塞了所有MCP线程;它始终未能自行恢复,因此运维人员每小时要手动执行数次主节点故障转移。第二处创伤:一次打包变更悄然将该服务的线程数上限压到了低于预期安全值的水平,而最近的“修复”——即将其回滚——只在生产峰值时才耗尽数据库连接池,迫使再次回滚。
周日,账户服务在UTC 18:30至20:20期间宕机:Memcached不稳定导致Nginx在100毫秒超时上阻塞,直至其工作线程耗尽,健康检查被淹没,负载均衡器摘除了所有节点——全球范围内的登录都被阻断。当晚,XMPP社交层在一次紧急蓝绿故障转移中失效:重连的登陆潮冲垮了好友服务的负载均衡器,而后者无法配置替代节点,因为其子网已没有空闲IP。玩家虽然连接上了,但看到所有好友都显示为离线——一个“黑屋子”。
云服务上限让情况雪上加霜:数千台c4.8xlarge实例逼近了该区域的实例上限,而提供251个可用IP的/24子网也已被耗尽,拖长了负载均衡器的恢复时间。Epic将MongoDB专家空运到现场,承诺对消息栈和MCP进行重新架构,并在复盘报告结尾附上了一则招聘广告——一支由资深在线开发者组成的小团队曾让全球最大的PC/主机游戏保持在线,直到数字增长超出了他们的能力。
代价是什么
2018年2月3日至4日期间发生了六起部分及完全的服务中断:登录被阻断、匹配冻结、好友显示为离线;手动故障转移每小时都在进行。
为什么会发生
匹配状态存放在一个共享分片上;当它的写入器排队时,所有MCP操作都被阻塞,而唯一的恢复手段就是手动主节点故障转移。
一次打包变更将MCP服务的线程数上限压到了低于安全默认值的水平;而这一修正本身又在仅在生产峰值时才耗尽数据库连接池,不得不被回滚。
所有账户服务流量都经过一个Nginx代理,其工作线程在100毫秒的Memcached超时上阻塞;饱和的工作线程导致健康检查失败,负载均衡器随即摘除了所有节点。
好友服务的故障转移路径需要一个/24子网中的空闲IP——即251个地址——而重连的登陆潮在事件进行中就将它们耗尽。
XMPP运行着一个全互联集群(101个节点,仅集群链路每个节点就有约1000个套接字),且存在硬性的节点上限,因此社交层的容量无法简单地增加。
教训
增长超越架构的速度快于招聘能修复的速度:在50倍规模下,一个未经测试的线程设置、一个251个IP的子网和一个热点分片,每一个都会变成宕机。
后续
复盘报告的修复清单读起来像一项重新架构计划:与现场专家一起对MongoDB写入队列进行根因分析,将匹配会话迁移到内存存储,将非验证流量绕开Nginx/Memcached组合,修复子网容量,并通过将核心服务分散到多个区域和云上来缩小影响范围。随着游戏持续增长,Epic继续发布《堡垒之夜》服务更新,而这份复盘报告成为了一个标准引用案例,说明病毒式增长如何将每一处潜在的配置错误转化为宕机。
从这里,追溯依据
参考来源
- Postmortem of Service Outage at 3.4M CCU Epic Games (Fortnite news) · epicgames.com ·
- Postmortem of Service Outage at 3.4M CCU (archived copy) Internet Archive Wayback Machine · web.archive.org ·
- Postmortem of Service Outage at 3.4M Concurrent Users (discussion) Hacker News · news.ycombinator.com