AI实践哪家强?来 AICon, 解锁技术前沿,探寻产业新机! 了解详情
写点什么

Slack 蜂窝架构迁移:背后的技术策略与挑战

作者丨Cooper Bethea

  • 2023-09-12
    北京
  • 本文字数:3321 字

    阅读完需:约 11 分钟

大小:1.83M时长:10:38
Slack蜂窝架构迁移:背后的技术策略与挑战

近年来,蜂窝架构(Cell-Based Architecture)作为一种增加冗余和有效限制站点故障影响范围的方式,在大型的在线服务中越来越流行。为了实现这些目标,在过去的一年半里,我们将 Slack 最关键的面向用户的服务从单体架构迁移到了基于蜂窝的架构。在本系列文章中,我们将解释我们为什么要进行大规模迁移、介绍蜂窝拓扑设计以及我们在此过程中所做出的工程技术权衡,并讨论我们成功对许多相连接的服务进行深度改造所采用的策略。

 

背景说明:事故



2021 年 6 月 30 日事故中的 TCP 重传图表

 

在 Slack,我们会在每一次发生明显的服务中断后进行一次事故评审。以下是我们内部事故评审报告的一些摘录,总结了其中的一起事故和我们的发现:

 

太平洋时间 20121 年 6 月 30 日上午 11 点 45 分,我们的云供应商在美国东海岸的一个可用区域发生网络中断,Slack 的大部分服务都托管在那里。连接一个可用区域和其他几个包含 Slack 服务器的可用区域的网络链路发生了间歇性故障,导致 Slack 服务器之间的连接变慢,进而出现服务降级。

 

太平洋时间 2021 年 6 月 30 日下午 12 点 33 分,我们的云供应商自动从服务中删除了网络链接,恢复了对 Slack 客户的全部服务。经过他们的一系列自动检查之后,网络链接再次进入服务状态。

 

太平洋时间 20121 年 6 月 30 日下午 5 点 22 分,网络链路又发生了同样的间歇性故障。下午 5 点 31 分,云供应商永久地从服务中删除了网络链接,恢复了对我们全部的服务。

 

乍一看,这似乎没什么大不了。我们的服务所使用的一块物理硬件发生了故障,因此出现了一些错误,直到发生故障的硬件被移除。然而,在进行事故评审时,我们不禁问自己:让我们的用户体验到这样的中断是合理的吗?

 

Slack 运营着一个全球性的、多区域的边缘网络,但我们的大多数核心计算基础设施都位于单个地区(us-east-1)的多个可用区域内。可用区域(AZ)是指单个区域内的隔离的数据中心,它们除了可以提供物理隔离之外,也会限制我们所依赖的云服务组件(虚拟化、存储、网络等)的故障影响范围,这样就不会在多个 AZ 中同时发生故障。在云端托管服务的构建者(如 Slack)可以通过这样的一种方式来构建服务——在一个区域内整个服务的可用性高于任何一个 AZ 的可用性。那么问题来了:为什么这个策略在 6 月 30 日没有奏效?为什么一个 AZ 发生故障会让用户体验到中断?

 

事实证明,在分布式系统中检测故障是一个难题。来自用户的一个针对 Slack API 的请求(例如,在一个频道中加载消息)可能会扇出数百个发给后端服务的 RPC,每个 RPC 都必须完成调用才能向用户返回正确的响应。我们的服务前端不断尝试检测和排除发生故障的后端,但在能够排除发生故障的服务器之前必须先将故障记录下来!让事情变得难上加难的是,我们的一些关键数据存储(包括我们的主数据存储 Vitess)提供了高度一致的语义,这对应用程序开发人员来说非常有用,但也要求任何写入都要有可用的后端。如果一个分片主节点对应用程序前端不可用,那么到该分片的写入将会失败,直到主分片返回错误或一个次分片被提升为主分片。

 

我们可以将上述的中断归类为灰色故障。在发生灰色故障时,系统可用性对于不同的组件来说是不一样的。在我们的事故中,受影响 AZ 内的系统看到其 AZ 内的后端完全可用,但 AZ 外的后端不可用。反过来,未受影响 AZ 内的系统看到受影响的 AZ 是不可用的。即使是同一个受影响的 AZ 内的客户端能够看到的后端可用性也是不一样的,这取决于它们的网络流量是否碰巧流经发生故障的设备。这就好比要求分布式系统在为我们的客户处理消息和提供小动物动图的同时处理好一切故障,这是一个相当复杂的任务。

 

我们对这个难题的解决方案并不是试图去自动修复灰色故障,而是通过利用人类的判断力来让计算机的工作变得更容易。工程师们很清楚,在发生宕机时,主要的问题在于一个 AZ 不可达——我们汇总的目标 AZ 的每一张图表都与上面的重传图很相似。如果我们有一个可以告诉所有系统“这个 AZ 已坏,请避开它”的按钮,我们肯定会把它盘得发亮!因此,我们开始着手构建这样的按钮,可以将流量从 AZ 中抽走。

 

我们的解决方案:AZ 就是会被引流的蜂窝单元

 

与其他许多基础设施一样,AZ 引流按钮在概念上很简单,但在实践中却很复杂。我们的设计目标是:

 

  1. 尽可能在 5 分钟内减少 AZ 内的流量。Slack 的 99.99%可用性 SLA 只允许我们每年不到 1 小时的总体不可用,因此,为了有效地保持这种可用性,我们需要能够快速奏效的工具。

  2. 引流不能导致对用户可见的错误。引流是一种通用的缓解措施:只要故障包含在单个 AZ 内,即使尚未清楚导致故障的根本原因是什么,也可以有效地使用引流来缓解故障。这是一种实验性的方法,在发生故障期间,运维人员可以尝试对 AZ 进行引流,看看故障是否能够恢复,如果不能,则进行放流。如果引流会导致额外的错误,那么这种方法就没有用了。

  3. 引流和放流必须是增量的。在放流时,运维人员将流量的 1%分配给 AZ,看看它是否已经恢复。

  4. 引流机制不能依赖于被引流的 AZ 内的资源。例如,只是通过向每台服务器发送 SSH 命令并强制其关闭健康检查机制来激活引流是不行的。这是为了确保即使 AZ 完全离线也可以进行引流。

 

一种符合这些需求的简单实现是向每个 RPC 客户端发送一个信号,当客户端接收到这个信号时,它们会让流向特定 AZ 的一定百分比的流量失败。这个方案隐含了很多复杂性。Slack 没有共享代码库,甚至没有共享运行时,处理用户请求的服务使用多种语言编写,如 Hack、Go、Java 和 C++,这就需要为每一种语言单独实现客户端。除此之外,我们还支持许多内部服务发现接口,包括 Envoy xDS API、Consul API,甚至 DNS。况且,DNS 没有为 AZ 或部分引流等机制提供抽象,客户端只希望能够解析 DNS 地址并接收 IP 列表。最后,我们在很大程度上依赖了开源系统,如 Vitess,要修改代码,就需要在内部维护分支,并做一些额外的工作,将变更合并到上游,这并不是一份令人愉悦的差事。

 

我们采用的主要策略叫作“筒仓(Siloing)”。如果服务只从其所在的 AZ 内接收流量,并且只向该 AZ 内的服务器发送流量,那么这个服务就可以被称为一个筒仓。从整体上看,这种架构的效果是:每个服务似乎都有 N 个虚拟服务,每个 AZ 中有一个。重要的是,我们可以通过对某个 AZ 内的用户请求进行重定向来有效地将 AZ 内所有筒仓服务的流量抽走。如果没有来自用户的新请求到达筒仓所在的 AZ,那么这个 AZ 的内部服务自然会停止,因为它们没有新的工作要做。



我们最初的架构,后端分布在各个 AZ 中,因此错误会出现在所有 AZ 的前端

 

最终,我们得到了一个蜂窝架构。所有服务都存在于所有 AZ 中,但每个服务只与其 AZ 内的服务通信。一个 AZ 内的系统故障被包含在该 AZ 内,我们可以动态路由流量以避开这些故障,只需在前端重定向即可。



筒仓架构,一个 AZ 中的故障被包含在该 AZ 中,流量可能被抽走

 

有了筒仓架构,我们就可以将精力集中在一个地方来实现流量转换:将来自用户的查询路由到 us-east-1 区域的核心服务。在过去的几年里,我们进行了大量投入,从 HAProxy 迁移到了 Envoy/xDS 生态系统,因此我们所有的边缘负载均衡器现在都在运行 Envoy,并从我们内部的 xDS 控制平面 Rotor 接收配置。因此,我们能够通过简单地使用两个开箱即用的 Envoy 功能来进行 AZ 引流:加权集群和基于 RTDS 的动态权重分配。在对一个 AZ 进行引流时,我们只需通过 Rotor 向边缘 Envoy 负载均衡器发送一个信号,指示它们在 us-east-1 重新分配每个 AZ 的目标集群权重。如果 us-east-1 某个 AZ 的权重变为零,Envoy 将继续处理请求,但会将所有新请求分配给另一个 AZ,也就完成了对这个 AZ 的引流。我们来看看这是如何满足我们的目标的:

 

  1. 通过控制平面的传播为秒级,Envoy 负载均衡器将立即应用新的权重。

  2. 引流不会丢失请求,负载均衡层不会放弃任何一个查询。

  3. 权重提供粒度为 1%的增量式引流。

  4. 边缘负载均衡器完全位于不同的区域,控制平面有区域副本,可以抵御任意的单 AZ 故障。

 

下图是我们逐步将流量从一个 AZ 引到另外两个 AZ 时每个 AZ 的带宽情况。注意图中的“膝盖”部分,它反映了 Envoy/xDS 实现为我们提供的快速、大粒度的传播保证。



单 AZ 的每秒查询走势

  

原文链接:


https://slack.engineering/slacks-migration-to-a-cellular-architecture/


相关阅读:


自定义跟踪架构:Slack 高效解决通知问题

Slack实时消息处理架构,更新、更快、更稳定

Slack工程师如何解决最常见的移动开发痛点

Zoom和Slack的第二曲线

2023-09-12 09:496855

评论

发布
暂无评论
发现更多内容

华为云网站安全解决方案:为您的企业保驾护航,助力安心创造未来!

IT科技苏辞

OctConv:八度卷积复现

华为云开发者联盟

人工智能 华为云 卷积 华为云开发者联盟 企业号 4 月 PK 榜

持续领先同行?看华为云EI如何助力企业智能化转型

爱尚科技

谷歌研究科学家:ChatGPT秘密武器的演进与局限

OneFlow

华为云EI:引领企业智能化转型,助力全球行业创新

爱尚科技

在 plist 中轻松转换两种格式

JMeter CSV 参数文件的使用方法

Liam

软件测试 测试 Jmeter csv

【异常解决】UnknownHostException: api.weixin.qq.com 的解决方案

No8g攻城狮

小程序 微信 Java EE

嘉为蓝鲸携手腾讯云亮相石油石化峰会!

嘉为蓝鲸

能源 嘉为蓝鲸 研运一体化

深度学习:理解卷积神经网络(CNN)的原理和应用

兴科Sinco

人工智能 神经网络 深度学习 自然语言 图象识别

海外 SaaS、工具、技术栈实用指南

SaaSLab

SaaS 技术栈 海外市场

这样也行,在lambda表达式中优雅的处理checked exception

程序那些事

Java stream 程序那些事

SELECT COUNT(*) 会造成全表扫描?回去等通知吧

程序员大彬

Java MySQL

华为云网站安全解决方案,如何保障中小型企业云上云下安全?

IT科技苏辞

在线Plist文件格式转Json文件格式

MobTech 秒验|极速验证,拉新无忧

MobTech袤博科技

华为云FusionInsight引领现代数据平台革新:助力企业数字化转型与增值

科技怪授

基于低代码开发平台打造新时代OA系统

力软低代码开发平台

如何打开 plist 文件

ios 开发 IPA上传

Dapr和Rainbond集成,实现云原生BaaS和模块化微服务开发

北京好雨科技有限公司

云原生 #Kubernetes# Baas rainbond 企业号 4 月 PK 榜

DriveGPT自动驾驶大模型中国玩家首发!1200亿参数,毫末智行出品

Openlab_cosmoplat

人工智能 自动驾驶 机器学习 开源社区 ChatGPT

走进 RocketMQ(六)事务消息的设计

白裤

Java RocketMQ 事务消息 最终一致性

Django笔记八之model中Meta参数的使用

Hunter熊

Python django model meta

架构实战营第10期模块八作业

刘博

解锁企业数据管理的利器——DataOps

数造万象

华为云EI引领行业智能化转型:赋能全球企业,共创智能未来

爱尚科技

华为云网络安全解决方案,云上云下一体助力企业安心发展

IT科技苏辞

华为云网站安全解决方案:中小型企业的IT安全利器

IT科技苏辞

走进 RocketMQ(五)高性能文件读写

白裤

Java RocketMQ 消息队列 文件读写优化

Slack蜂窝架构迁移:背后的技术策略与挑战_架构_InfoQ精选文章