自2019年10月起持续记录

事后剖析:二十六分钟登录失败,2026年1月19日

我们归类为配置的会话存储更改导致所有客户在二十六分钟内无法登录面板和 API。运行中的实例从未受到影响。

摘要

2026年1月19日,UTC时间14:02至14:28之间,大约三分之二的面板登录或API认证尝试失败。现有会话也被随机失效。运行中的实例、其网络和流量全程未受影响。配置供应暂停了二十六分钟,随后排空;没有订单丢失。

时间线

所有时间均为UTC,2026年1月19日。

时间事件
14:02会话令牌架构变更应用于控制平面。发布被标记为配置,因此同时应用于所有六个面板节点。
14:03登录错误率从接近零升至百分之六十一。自动告警有两分钟窗口,尚未触发。
14:06告警触发。值班工程师收到寻呼。
14:08第一响应人上线。看到错误率,代码变更日志中没有部署记录,开始查看数据库。
14:14第二位工程师加入,检查配置变更日志而非代码日志,找到了14:02的条目。
14:16原因已明确:两个节点正在使用旧的读取器验证令牌。
14:19开始回滚。
14:24令牌在所有六个节点上正确签发和验证。错误率降至零。
14:28排队的配置供应作业排空。恢复完成。
15:10状态页面更新。晚了四十二分钟,这本身就是一次失败,将在下面讨论。

根本原因

会话令牌增加了一个字段。写入方立即发出了新格式;六个面板节点中有两个节点的读取器尚未重启,拒绝接受任何携带新字段的内容。请求分布在所有六个节点上,因此在新区块上生成的会话在任何给定请求中被旧节点验证的可能性约为三分之一。结果看起来是间歇性的,这就是为什么诊断的前六分钟花在了数据库而不是部署日志上。

更深层次的原因是我们2023年写的一条规则。触及架构文件而非应用程序代码的变更被归类为配置,而配置跳过了金丝雀阶段,理由是“只是值”。当架构文件仅包含功能开关时,这条规则是合理的。随着架构文件定义扩大,没有人重新审视它,这次变更被正确归类为一条已经悄然变错的规则。

这不是应用它的工程师的错误。分类完全按照书面规则执行。

爆炸半径

  • 面板登录:二十六分钟内百分之六十一的失败率。
  • API令牌:相同的失败率,相同的时间窗口。幂等键确保重试的创建不会重复。
  • 运行中的实例:未受影响。无数据包丢失、无重启、无存储影响。
  • 配置供应:暂停,并非失败。窗口期内有四个订单结算,并在14:28前全部完成。

我们更改了什么

  1. 金丝雀阶段现在是无条件的。任何部署,无论分类如何,在去往任何其他地方之前,都会先经过一个节点进行五分钟的合成流量测试。完成于1月21日。
  2. 读取器接受先前格式三十天。令牌验证现在显式版本化,带有重叠窗口,因此部分推出的变更会退化为完全无影响。完成于1月23日。
  3. 每十五秒运行一次合成登录,从我们网络外部,在三个地区,并且在连续第二次失败时立即寻呼,而不是等待两分钟的平均窗口。完成于1月22日。
  4. 合成登录失败两次时,状态页面自动发布,无需等待人员编写句子。随后会有人工句子。完成于1月26日。

我们没有更改什么,以及原因

我们仍然不记录客户端IP或请求体用于面板流量。如果记录了,可能会立即显示跨节点的三分之一分布,并可能节省九分钟。九分钟不值得对每个客户的登录来源进行永久记录。日志页面上的保留表保持不变。

我们没有将会话迁移到共享的跨站点存储中。跨所有站点的单一会话存储可以通过一个读取器完全避免混合读取器问题。但它也会创建一个集中、始终热点的记录,记录谁连接了什么,这是我们六年未曾构建的。

我们没有在状态页面之外增加故障公告渠道。有几个人建议使用社交媒体。状态页面是我们运营的、我们可以承诺保持准确的唯一事物,增加第二个表面意味着增加一个会过时的表面。

信用额度

SLA涵盖实例可用性。实例在整个二十六分钟内可用,因此根据合同,没有人有权获得赔偿。我们对窗口中存在认证失败的每个账户应用了一天信用额度,总计约三千一百欧元,因为与无法登录服务器的人争论这一区别对每个人下午时间的利用都更糟。

随时恭候

选择城市,选择大小,用加密货币支付。

无需填写关于您的身份信息的表格,无需等待人工审批,无需电话验证。账单结清后,凭证将发送到您的邮箱。