本文描述了 2020 年 5 月 12 日导致 Slack 宕机的技术细节,要想了解更多关于此故障背后的过程,请参阅 Ryan Katkov 的文章 All Hands on Deck (1)。
2020 年 5 月 12 日,Slack 发生了很长时间以来的一次重大故障。我们在事件发生后不久就发表了一份故障说明(2),但这是一个有意思的问题,我想更详细地介绍一下围绕它的一些技术问题。
用户可见的访问中断,开始于太平洋时间下午 4:45,但问题真正开始于当天早上 8:30 左右。我们的数据库可靠性工程团队接到警报,部分数据库基础架构出现了明显的负载增加,同时我们的流量团队也收到了一些 API 请求失败的报警。数据库负载的增加是由于一个配置变更引起,它触发了一个长期存在的性能 bug,该变更很快被定位并回滚,它是一个功能开关,执行了基于按用户百分比的发布,因此这是一个快速的过程。我们对客户产生了一些影响,但只持续了三分钟,在整个上午的短暂事件中,大多数用户仍然能够成功发送消息。
这次问题的背景之一,是我们的主 Web 应用层的规模最近以来在显著扩大。我们的 CEO Stewart Butterfield 也提到过由于隔离以及远程办公对 Slack 使用的影响。由于疫情的关系,我们在 webapp 层中运行的实例数量明显高于 2020 年 2 月之前的时候。当 worker 跑满,我们会自动快速扩容,但 worker 等待一些数据库请求所需的时间则要长得多,导致利用率更高。我们在事件中增加了 75% 的实例数,最后达到了我们迄今为止,运行的最高数量的 webapp 主机。
在接下来的 8 个小时里,一切似乎都很好,直到我们收到告警,服务的 HTTP 503 错误比正常情况下增多。我们启动了一个新的问题响应通道,webapp 层的 on-call 工程师手动扩大了 webapp 的规模,作为初步的缓解措施。不寻常的是,措施根本没有帮助。我们很快就发现,webapp 集群中的一个子集处于重载状态,而其他 webapp 实例却没有什么流量。我们开始了多线索的排查,调查 webapp 性能和我们的负载均衡器层。几分钟后,我们发现了问题所在。
我们在 4 层负载均衡器后面使用 HAProxy 实例的集群来分发请求到 webapp 层。我们使用 Consul 进行服务发现,并使用 c