在AWS re:Invent大会上,CTO Werner Vogels分享了亚马逊在系统设计方面的一些基本经验教训。
译自Werner Vogels' 6 Lessons for Keeping Systems Simple,作者 Joab Jackson。
"实体不应无故增多"——威廉·奥卡姆,奥卡姆剃刀
且不说亚马逊网络服务 (Amazon Web Services),这家云巨头已经能够在其系统和服务上扩展超过二十年,不断推出新功能,同时保持用户体验易于管理。
在其惯例周四主题演讲中,AWS 首席技术官Werner Vogels分享了他二十年来在云巨头工作的经验中,关于保持简单的一些经验教训。
复杂性总是潜入系统设计中,因此工程师必须勤勉地管理这种复杂性。
目标始终是“以安全的方式扩展我们的系统,使其随着时间的推移变得更加复杂”,他说道。
从灵活到致命
目标不是消除复杂性,而是有效地管理它。
增强任何系统时的危险在于它带来了不必要的复杂性,这难以维护,并剥夺了用户的乐趣。
但正如 Larry Tesler所指出的,复杂性无法消除,只能转移。
现在,存在良好的复杂性,这是为了帮助系统发展而添加的;然后是那种在没有架构监督的情况下发生的复杂性,它只会减慢用户速度,并使系统更难以维护,他解释道。
复杂性不仅取决于系统中组件的数量,还取决于这些组件的排列方式。
"你无法将给定任务的复杂性降低到某个点以下。一旦达到这一点,你只能转移负担。"——Larry Tesler
在这里,Vogels 以自行车设计为例。
实际上,自行车最简单的形式是独轮车,它只有一个轮子。独轮车非常灵活("它们可以原地转弯"),但很难骑。
另一方面是三轮车,它们很容易骑,但笨重且难以操纵,任何骑过三轮车的人都知道。
最好的设计实际上是两轮自行车,它兼具易用性和灵活性。
"自行车有更多组件,但从整体角度来看,它是最简单的形式,"他说道。自行车成为最流行的自行车形式并非偶然。
将复杂性放在需要的地方。
Amazon S3(简单存储服务)就是一个例子,它只提供最终一致性,而不是强一致性。这意味着如果客户购买了 Amazon S3 存储桶,它最终会可用,但可能不会立即可用。
然而,客户希望获得强一致性,并已开始构建变通方案,以确保在其自身设计中基于 S3 实现强一致性,这导致了他们自身系统中不必要的复杂性。
AWS 最终重新设计了 S3 以实现强一致性,"将复杂性转移到需要的地方",即远离客户。
那么,系统工程师如何管理他们自己系统中的复杂性呢?
Vogels 提供了六个技巧:
1. 构建能够发展的系统
不向前发展的软件系统会消亡。即使是最稳定的软件也会看到世界在没有它的情况下前进。
此外,谁不想看到自己喜欢的应用程序拥有新功能或运行速度更快?
你的系统会随着时间的推移而发展,你需要修改你的架构,Vogels 建议道。
"每当你改变数量级时,你都需要重新审视你的架构,"Vogels 说。当 S3 推出时,设计工程师知道他们将改变架构。随着时间的推移,尽管其 API 的占用空间很小,但它积累了惊人的功能范围。
"你会看到,每年我们都会添加新功能,而不会对我们为客户提供的功能产生任何影响,"他说。
网络服务也是如此,在用户的请求下,网络服务得到了显著的发展。
"我们知道,无论我们在 2006 年为您提供的网络功能是什么,到 2010 年肯定会在 2020 年发生根本性的变化,"Vogels 说。
你需要制定一个策略来应对复杂性,这种复杂性会随着时间的推移在你的系统中增长。
Vogels 说,可进化性是管理复杂性的前提条件。
2. 打破复杂性
复杂性可能会潜入你的应用程序,就像谚语中青蛙汤里的热量一样。
"小的变化起初似乎很容易管理、很容易吸收,但如果你忽略了警告信号,系统就会变得越来越复杂,越来越难以管理和理解,"他说。 答案是将系统分解成多个更易于管理的组件。
Amazon CloudWatch最初是一个简单的监控服务。随着更多功能的添加,每个功能都加载到登录页面上,直到页面变得非常繁忙,AWS 才重新设计了它,使其只保留核心功能。其他功能被迁移到它们自己的环境中。
服务应该有多大?它应该能够容纳在一个工程师的脑子里。
“如果你无法记住它,你的服务通常就太大了,”Vogels 说。
3. 将架构与业务需求对齐
Vogels 说,通过完善的 API 构建具有“智能端点”和“细粒度接口”的业务重点组件。将它们分散,以便它们“独立发展”。
企业技术并非为了自身而构建。它是为客户而构建的。因此,系统架构师需要与他们服务的业务部门紧密合作。
协作至关重要。业务部门可能会说它需要 100% 的正常运行时间。这是可行的,但代价高昂。因此,系统设计师可能需要指出 100% 的可靠性将有多昂贵。
“然后你们就可以进行对话了,”他说。
Vogels 曾说过,一切都会一直失败。所以诀窍是计划失败。
4. 将工作组织成单元
随着应用程序的流行和功能的增加,它在操作方式上也会产生复杂性。考虑使用基于单元的架构来保持这种日益增长的复杂性的简单性。
“构建系统的时间通常比运行系统的时间要少得多。因此,提前投资可管理性至关重要,”Vogels 说。
管理这些操作也必须分解成更小的构建块。这是为了减少影响范围,这对于最大限度地减少停机时间至关重要。
“单元在复杂系统中创造秩序,”他说。“它们将问题隔离到特定单元,而不会影响其他单元。”
需要一个路由器和控制平面将请求路由到各个单元。路由标签可以基于区域 ID、主机 ID、客户 ID。
“随着时间的推移,分解成单元将有助于您维护客户的可靠性和安全性,”他说。
5. 设计可预测的系统
不确定性难以处理。因此,提前设计您的系统以减少不确定性。
AWS 为其面向客户的负载均衡器运行一个超平面,以处理数百万客户用来更改配置的所有更改。
令人惊讶的是,AWS 没有使用事件驱动架构来设置此服务,这与普遍的看法相反,对于此任务来说是一种糟糕的方法,因为来自用户的负载请求速率将是不可预测的。
相反,AWS 将更改写入 S3 文件,负载均衡器以定期轮询间隔提取这些文件。
“简单需要纪律”——AWS 首席技术官 Werner Vogels
“这是一种我们称之为持续工作的模式,”Vogels 说。这种方法避免了峰值、积压和瓶颈,并且还使系统能够自我修复,因为“S3 是不可渗透的。”
AWS 的Route 53域名服务在其运行状况检查器上采用相同的原理:轮询而不是排队。
6. 自动化所有事务
要管理复杂性,就自动化复杂性。
AWS 使用自动化来完成许多任务,甚至包括构建新的区域,这是完全自动化的。
问题不在于自动化什么,而在于什么不自动化。只有那些真正需要人工参与的决策才应该有人工干预。其他一切事情都应该自动化。
“自动化应该是标准,例外情况是我们需要人工参与,”Vogels 说。“手动输入只应在真正需要人工判断的领域中需要。”
安全是 AWS 的一个高度自动化的流程,其中包括自动化威胁情报等流程。AWS 每天收到“数万亿”个 DNS 更改请求,每天至少识别 100,000 个恶意域名,这通过一个自动化流程完成——这是一个手工无法完成的流程。
支持票证是另一个适合自动化的领域通过代理。代理最适合非常狭窄的用例,在这些用例中,它们被赋予了一系列工具,可以通过称为“无服务器提示链”的流程来解决问题。
如果代理无法解决问题,只需将其提请人工注意。
“自动化所有不需要高度判断力的事情,”Vogels 说。