Railway 这次故障有一个很反常的点:不是所有负载都真的停了,但用户还是访问不到。

根据 Railway 事故报告,5月19日22:20 UTC 至5月20日06:14 UTC,平台因 Google Cloud 将其生产账号错误置为暂停状态,出现约8小时服务中断;07:58 UTC,事故被标记为解决。

直接影响很清楚:Dashboard、API、数据库、GCP compute 下线。用户看到的是 503、404、无法登录、部署阻塞。

更要命的是,故障越过了 GCP 边界。Railway Metal 和 AWS 上的部分用户负载本身仍在线,但边缘代理依赖托管在 GCP 的网络控制面 API 来更新路由表。路由缓存过期后,这些负载就从外部“消失”了。

这篇事故真正值得看的,不是谁背锅,而是一个更工程化的问题:多云资源在线,不等于平台可达。

账号恢复很快,服务恢复很慢

Railway 的时间线里,GCP 账号访问在 22:29 UTC 恢复。距离确认根因只过了十来分钟。

但这不是服务恢复。账号能进,不代表磁盘、计算、网络、边缘路由都能同时回来。云平台故障常见的麻烦就在这里:控制权恢复只是第一步,依赖它的系统还要一层层重新站起来。

这次的关键时间点大致如下:

时间点进展用户看到什么
5月19日22:11Dashboard 返回 503无法登录,API 不可用
22:19确认 GCP 生产账号被暂停平台级故障定位到上游账号状态
22:29GCP 账号访问恢复账号恢复,但服务未恢复
22:35路由缓存开始过期Metal、AWS 负载开始出现 404
5月20日01:38边缘流量恢复服务网络层逐步恢复
02:47GitHub OAuth/webhook 因重试流量触发限流登录、构建再次受阻
04:00API、Dashboard、OAuth 确认可用剩余负载继续恢复
06:14主要中断窗口结束约8小时故障结束
07:58标记解决事故状态关闭

这里要避免一个误写法:不能说所有用户工作负载都实际宕机。

更准确的说法是,峰值时全区域工作负载不可达。部分非 GCP 负载仍在运行,只是平台边缘无法解析到它们。

对开发团队来说,这种故障更烦。应用进程可能没死,数据库也未必丢数据,但外部用户已经打不开服务。排障时,你会看到一个很别扭的状态:服务像是活着,又像是不存在。

问题不在“多云”,在热路径卡在单云

Railway 称其网络是 Metal、GCP、AWS 之间的 mesh ring,也有高可用互联。数据库也跨多个可用区运行。

这说明 Railway 不是完全没有冗余。问题更具体:工作负载可发现性依赖运行在 GCP 机器上的网络控制面 API。

缓存能拖一会儿,但缓存不是故障切换。等缓存过期,边缘代理拿不到新的路由表,Metal 和 AWS 上的负载即使在线,也会变成不可达。

这就是热路径的危险。

很多团队谈多云,容易只看资源层:机器在哪些云上,网络是不是互通,数据库有没有多可用区。可真正决定事故边界的,往往是控制面、服务发现、鉴权、构建、登录这些链路。

可以简单对照一下:

看起来的多云能力真正要追问的问题这次事故暴露的风险
计算资源分布在 GCP、AWS、Metal路由发现是否也跨云可用非 GCP 负载在线但不可达
网络有高可用互联控制面 API 是否依赖单一云缓存过期后边缘无法更新路由
数据库跨可用区quorum 是否跨云、跨设施运行单云实例消失时仲裁能力受考验
使用 GitHub OAuth/webhook重试风暴是否有保护恢复期触发限流,登录和构建受阻

这也不是说 PaaS 都不可信。PaaS 的价值本来就是替开发者屏蔽复杂基础设施。

现实限制在于,用户很难直接验证供应商控制面的真实依赖。状态页、SLA、架构说明、事故复盘,往往是少数可用线索。PaaS 用户买到的是抽象后的可靠性,但抽象层本身也要被审计。

目前还不能推断 Google Cloud 内部到底发生了什么。Railway 原文也在等待 Google 内部复盘确认。事故报告没有提到数据丢失、入侵或计费异常,这几个点不该硬加戏。

我更在意的是 Railway 自己承认的部分:供应商选择和架构依赖由自己负责。这个表态比单纯把问题推给上游更有信息量。

工程团队现在该问什么

Railway 的后续计划,方向很明确:把 GCP 从数据面热路径中移出,更多保留为 secondary/failover;把高可用数据库分片扩展到 AWS 和 Metal;重构数据面和控制面,让单一云的全部实例瞬间消失时,数据库仲裁仍能保持运行,并能快速迁移不可用工作负载。

这不是“换一家云”能解决的问题。换云只是在换单点。如果控制面仍在单一供应商上,事故边界还是会被那条热路径决定。

对云平台和基础设施工程师,最该做的是把依赖图画到控制面,而不是停在资源清单。

具体说,要补三类检查:

  • 路由发现.边缘代理的路由表从哪里来,缓存多久过期,失联后是降级还是失明。
  • 数据库仲裁.quorum 是否跨 AWS、Metal、GCP 生效,单云全灭时会不会卡住写入或恢复。
  • 恢复保护.OAuth、webhook、构建队列在重试洪峰下有没有限流、退避和隔离。

对依赖 Railway 或类似多云 PaaS 的开发团队,动作要更现实一点。

如果是生产系统,不必因为一次事故立刻迁移,但可以先延后把更关键的新服务压上去,等 Railway 公布更细的整改结果。已有业务要检查自己的外部兜底:DNS、状态页、降级页、备份部署方案,以及能否在 PaaS 控制面不可用时保留最小服务能力。

如果正在采购或续约,多问四个问题,比问“你们是不是多云”更有用:

决策场景该问的问题可能的动作
准备上生产控制面和服务发现是否跨云可用延后关键业务上线,等待整改细节
已经依赖 RailwayPaaS 控制面不可用时,业务是否还有兜底入口补 DNS、降级页、备份部署预案
评估多云 PaaS登录、构建、webhook 是否依赖单点把这些链路纳入供应商审查
做内部基础设施缓存过期后系统是降级还是不可达为路由发现设计失联模式

接下来最该观察的不是道歉措辞,而是三件工程结果。

Railway 会不会公开新的路由发现架构;数据库 quorum 是否真的跨 AWS、Metal、GCP;GitHub OAuth 和 webhook 的重试风暴是否能被限流保护吸收。

如果这三件事没有交代清楚,多云听起来再完整,也只能说明资源分散了,不能说明故障边界被切开了。

回到开头那个反常点:负载还在,用户却访问不到。它提醒的是一个老问题,牵一发而动全身。多云架构最怕的不是少一朵云,而是所有云都要经过同一扇门。