单元化架构,分布式系统的新王!

news/2024/10/20 21:05:33

0 关键收获

  • 单元化架构通过减少故障的爆炸半径来增加系统弹性
  • 单元化架构是那些任何停机时间都被认为是不可接受的,或者可以显著影响最终用户的系统的一个好选择
  • 单元化架构通过强制使用固定大小的单元作为部署单元,并倾向于扩展而不是扩展的方法,增强了微服务的可伸缩性模型
  • 单元化架构通过将各种组件(可能是微服务)打包并部署为单元,而不是在应用程序服务的粒度级别上,使它们在更广泛的系统上下文中的位置更清晰
  • 单元化架构通过在单元周围应用额外的安全层来帮助提高分布式系统安全性

本文是[单元化架构:如何构建可扩展和弹性系统]系列的一部分。在这个系列中,我们展示了一个发现之旅,并提供了对单元化架构的许多关键方面的全面概述和深入分析,以及将这种方法应用于现有和新架构的实用建议。

业务架构是一个存续了20多年的概念,至今也未有官方的定义,说明业务架构一个涵盖具有广泛包容性的概念,在不同场景和语境下它可能包含至少如下的含义:

  1. 实现业务需求的技术架构
  2. 在基础架构/中台架构之上的包含具体业务功能的架构层
  3. 更宏观的,支持企业战略实现的能力布局,也可以称为业务架构

存在即合理,本专场不求对概念做清晰的阐释,意在为大家展示此概念下的各种可能行,展示不同业务下不同环境下技术人员如何利用或成熟的,早期的或者创新的技术来解决业务问题,提升业务效率。当然,我们更倾向于选择具有创新意义的话题,譬如:

  • Cell-based架构:最近出现的一种架构模式,微服务架构大家都非常熟悉了,在这个架构中采用的是“所有人都可以互相通信”的原则。在单元化架构中增加了路由策略,服务会优先调用同一单元(Cel)中的其他服务,Cell可以是可用区域也可以是任何其他的自定义的访问范围。Cell-based架构可以显著节省成本,减少了延迟提高性能。同时也可以提高可用性,因为故障的爆炸半径被缩小为一个单元,其他单元完全不受影响,可以正常运行。

    Roblox、Slack 和 DoorDash 只是实施单元化架构并取得显著改进的公司的几个例子。我们相信这是一个创新趋势,许多公司将开始采用,因为他们希望调整分布式系统的规模、控制成本并提高系统弹性。

  • 数据驱动架构:一定程度上在基于业务数据做架构决策,从数据中识别出可广泛应用的明确的趋势是非常具有挑战性的。所以在数据驱动架构下,复杂的数据分析平台不再是系统的附加功能,而是升级为了业务架构的的核心部分之一。

软件开发面临主要挑战之一是扩展性。无论你在创业公司还是大型企业,评估如何交付一个新产品或功能时,系统应该如何可靠地处理不断增加的负载的问题不可避免地出现。

构建和运营现代分布式系统的挑战随着规模和复杂性的增加而增加。基础设施资源,无论是在云中还是在本地,都可能经历难以排查的意外故障,架构组件需要处理这些故障以提供所需的可用性。

1 单体、微服务和弹性挑战

几年前,微服务及其相关的架构变得流行,因为它们帮助解决了单体应用程序(monorepos)面临的一些扩展挑战。

正如Susan Fowler在几年前接受InfoQ采访时提到的,这些应用程序可能不支持足够的并发或分区,因此会达到导致性能和稳定性问题的可扩展性限制。随这些单体应用程序的增长,它们在本地环境中的工作变得更加具有挑战性。应用程序部署变得越来越复杂,导致团队的开发速度会急剧下降。

微服务通过使团队能够独立工作、部署和扩展服务来缓解这些问题。然而,像大多数事物一样,没有什么是无缺陷的,微服务也有挑战。其中一个是,微服务架构非常细粒度,以至于达到了单个服务的水平。因此,开发团队将缺乏对他们拥有的各个微服务在更广泛的系统上下文中的使用位置的知识。了解其他团队拥有的哪些微服务将更感兴趣也将更具挑战性。

随着时间的推移,这些挑战在微服务架构变得更加复杂时变得更加突出。此外,随着云基础设施的广泛采用,许多公司现在管理着从计算到存储再到网络和支持服务的大量云资源。这些资源中的任何一个都可能经历失败,可能导致服务的轻微或显著降级,尽管使用了冗余和故障转移机制,但如果没有采取特殊措施,一些故障模式不能完全被遏制。

2 基于单元架构的复兴

与故障隔离相关的挑战并不新鲜,也不特定于微服务或云。随着软件系统变得分布式以适应不断增加的负载需求,由于其分布式特性,必须考虑许多新的故障模式。

单元化架构首次出现在SOA时代,作为在大型分布式系统中管理故障并防止它们影响整个系统可用性的尝试。这些公司如Tumblr、Flickr、Salesforce或Facebook的初始实现 旨在使用自包含的单元作为并行化的单元来管理基础设施和应用程序资源,并隔离故障,将故障的爆炸半径限制在只有一部分客户或用户群体(一个分片)。

单元化架构,首先,是舱壁模式的一种实现,这是软件工程从造船业采纳的一个概念。舱壁 是船体结构中的水密垂直隔板,以防船体破损时水淹没整个船。

舱壁正在保护船只免受洪水蔓延

多年来,舱壁模式一直被宣传为现代架构的关键弹性模式之一,特别是微服务。然而,由于额外的复杂性,采用率一直很低,因此大多数公司选择将工作重点放在其他地方。

一些高调的公司最近选择重新审视单元化架构方法,以满足其基于微服务的、云托管平台的高可用性要求:

  • Slack已经将其大部分关键面向用户服务迁移到使用基于单元的方法 ,因为在AWS可用区域网络故障后经历了部分停机
  • Doordash 实现了基于其Envoy基础服务网格的区域感知路由 ,转移到基于AZ的单元架构,并减少了跨AZ数据传输成本
  • 反过来,Roblox 正在将其基础设施重新组织为单元以提高效率和弹性 ,因为它继续扩展

这些公司的共同点是,它们在云或私有数据中心的大型基础设施上运行微服务架构,并且由于基础设施或应用程序故障的无限爆炸半径,经历了严重的停机。作为回应,它们采用了单元化架构,以防止故障导致广泛停机。

亚马逊网络服务(AWS)一直是基于单元架构的长期采用者和倡导者,并在2018年的年度re:Invent会议上 和2022年再次 介绍了它。该公司还于2023年9月发布了关于基于单元架构的白皮书。

3 基于单元架构的构建块

在高层次上,单元化架构由以下元素组成:

  • 单元 - 自包含的基础设施/应用程序栈,提供故障边界;负责处理应用程序工作负载
  • 控制平面 - 负责提供资源、部署应用程序服务、确定路由映射、提供平台可观察性、移动/迁移数据等。
  • 数据平面 - 负责根据数据放置和单元健康(由控制平面确定)适当路由流量

为提供容错好处,单元化架构旨在支持单元级别的隔离和控制平面与数据平面之间的低耦合。重要的是要确保数据平面可以在没有控制平面的情况下运行,并且不应直接依赖于控制平面的健康状况。

4 单元作为一等架构构造

采用单元化架构提供了有趣的好处组合。单元首先在基础设施级别提供故障边界,指定的单元实例用于服务特定部分的流量,将故障隔离到用户或客户群体的一个子集。然而,它们也提供了将相关应用程序服务分组到特定于域的集群中的机会,帮助与架构和组织结构对齐,促进高内聚和低耦合,并减少工程团队的认知负担。

对于小型系统或当开始单元化架构采用工作时,完全有可能有一个单元包含所有应用程序服务。对于具有许多应用程序服务的大型系统,可以使用多个单元根据域边界组织架构。这种方法可以帮助更大的组织采用产品思维,并使系统架构与产品域和子域对齐。这对于由数十或数百个团队构建和运营大型产品组合的大型微服务系统尤其重要。

单元化架构结合了域和故障隔离边界

img

从容错的角度来看,一个单元(或单元实例)是一个完整的、独立的基础设施栈,包括它运行和为指定部分的流量服务所需的所有资源和应用程序服务实例(由单元分区策略确定)。至关重要的是尽可能隔离单元以保持故障包含。理想情况下,单元应该独立于其他单元,并且不共享任何状态或具有共享依赖项,如数据库。任何单元间通信应该保持在最低限度;理想情况下,应该避免同步API调用。相反,应该使用异步、消息驱动的数据同步。如果无法避免API交互,它们必须通过单元路由器进行,以便不会破坏基于单元架构的故障隔离属性。

关于单元部署选项的许多考虑因素包括选择单个或多DC(数据中心)部署,并确定最优的单元大小。一些组织采用了单个DC部署的单元化架构,其中所有基础设施和应用程序资源的单元实例都位于同一个数据中心或可用区域。这种方法最小化了多DC部署的灰色故障影响,并简化了健康监测(单元要么健康,要么不健康)。另一方面,如果使用得当,多DC部署可以在DC级故障的情况下提供弹性,但健康监测变得更加具有挑战性。

单元大小也可以在管理故障影响和管理基础设施成本方面发挥重要作用。使用较小的单元可以减少影响范围(受影响的用户/客户较少),提高资源利用率(由于较高的单元占用水平,闲置资源较少),并限制重新路由流量段到其他单元所需的工作。然而,如果单元大小太小,可能会在服务非常大的客户/客户时带来挑战,因此单元应该足够大,以迎合基于分区键的最大流量段。

另一方面,单元越大,在资源方面就越大的经济规模,这意味着更好的容量利用。管理较少的单元数量可能对运营团队来说更容易。此外,对于较大的单元大小,需要小心考虑基础设施限制,例如云提供商平台的区域和帐户级别限制。

5 控制平面管理单元化架构

采用单元化架构需要大量的努力来开发超出支持常规微服务架构所需的管理功能。除了提供和部署基础设施和应用程序服务之外,单元化架构还需要额外的功能,专门用于管理和监控单元、在可用单元中划分和放置流量以及迁移数据。

基于单元架构的主要考虑是如何在单元之间划分流量,应分别针对每个域使用面向单元的方法来确定。制定最佳分区方案的第一步是选择分区键。在大多数情况下,这可能最终是一个用户或客户标识符,但选择应针对每种情况单独进行,考虑流量段的粒度,以避免大于所选单元容量的段。

单元分区可以使用不同的映射方法

img

实现单元分区映射的方法有很多,它们各自的优缺点。这些方法从完整映射(存储所有映射记录)到使用一致性哈希算法,提供相当稳定的项目分配给桶,并在添加和删除桶时最小化混乱。无论选择哪种映射方法,提供覆盖能力都是有帮助的,以允许对某些分区键进行特殊处理,并协助测试活动。

其次是当新用户/客户加入或新单元被提供时的单元放置策略。该策略应考虑每个单元的大小和可用容量以及可能发挥作用的任何云提供商配额/限制。当单元容量阈值达到,并且需要一个新的单元来容纳到达平台的流量时,控制平面负责提供新的单元并更新确定数据平面路由应用程序流量的单元映射配置。

与上述相关的是数据迁移能力,这对于单元放置(如果需要重新洗牌分区)或在事件(如果单元变得不健康并需要被排空)中非常重要。从技术角度来看,数据迁移本质上是非常具有挑战性的,因此这种能力是提供单元化架构最困难的方面之一。相反,在不同单元中的数据存储之间迁移或同步底层数据开辟了关于数据冗余和故障转移的新可能性,进一步提高了采用单元化架构所提供的弹性。

6 数据平面路由应用程序流量

尽管控制平面负责管理架构,但数据平面可靠地移动流量数据。在单元化架构的背景下,这意味着将流量路由到适当的单元,如分区映射记录所确定的。需要强调的是,路由层需要尽可能简单和水平可扩展,并且应避免复杂的业务逻辑,因为数据平面是单点故障。

路由层实现可以采用从DNS和API网关到部署在通用计算或基于容器的执行平台上的定制应用程序服务的解决方案。无论哪种情况,分区映射数据必须能够从可靠的数据存储中读取,可能是一个高可用的分布式数据库或blob存储服务。路由层可以支持同步API调用(HTTP或GRPC)和异步消息,尽管后者可能更难以实现。

单元路由器作为主要数据平面组件

考虑到它在单元之间流量流动中的关键作用,数据平面可以实施安全策略,以确保只有经过授权的API请求才能由单元内的服务提供。因此,可以实施一系列安全机制来保护免受未经授权的访问,包括OAuth或JWT、用于认证的相互TLS以及用于授权的RBAC或ABAC。

7 使用基于单元架构的好处

采用基于单元架构的主要好处是通过故障隔离提高弹性。单元提供故障隔离边界,并减少部署失败、客户端滥用产品/平台、运营商错误或数据腐败等问题的影响。

使用单元还可以帮助系统的可扩展性。理想情况下,单元应该限制在大小上,以减少故障的爆炸半径,这也使单元成为扩展平台的一个很好的单元。随着时间的推移,工作负载增加,可以提供更多的单元来迎合新的流量(新客户/用户)。限制单元大小减少了来自任何非线性扩展因素或意外的争用点(性能瓶颈)的惊喜风险。

同样,单元可以用于部署范围。而不是在任何地方都推出服务的新版本,组织可以在将其更改推广到更广泛的用户/客户群体之前,使用限定在单元(因此是用户/客户子集)的金丝雀部署。

大小受限的单元非常适合量化系统的性能,因为测试单个单元的性能并根据扩展整个单元而不是扩展单元内组件来建立系统的可扩展性特征更容易。

单元提供了将属于同一子域或有界上下文的服务分组的额外好处,这可以帮助组织将团队和部门边界与产品域边界对齐。这对于大型组织尤其相关,这些组织中有数十或数百个团队构建和运营大型产品组合。

最后一个潜在的好处可能是从减少跨AZ流量中节省成本,但这应该与运行数据平面内的路由层相关的任何额外运营成本进行权衡。

8 采用基于单元架构的考虑

虽然单元化架构在分布式系统的背景下提供了许多优势,但实施这种方法需要额外的努力并引入挑战,因此可能不是每个组织,如仍在寻找产品市场契合度的初创公司,都适合投资。像微服务架构一样,单元化架构需要在底层平台上进行重大投资,以便这种架构能够加速团队的速度,而不是阻碍它。

考虑到大多数具有非平凡基础设施足迹的公司可能会面临过去促使其他人采用基于单元架构的挑战,仍然值得评估基于单元的方法是否值得追求。

首先,任何因声誉、财务或合同要求而无法承受广泛停机的公司都应该强烈考虑采用单元化架构,即使不是全部,至少对于关键的面向用户服务也是如此。

此外,任何需要或希望低恢复点目标(RPO)或恢复时间目标(RTO)的系统也应该考虑基于单元的方法。最后,需要在租户级别提供严格的基础设施级隔离的多租户产品也可以从单元化架构中受益,以提供完全专用的租户能力。

任何情况下,应该考虑采用基于单元架构的总成本,并与预期的好处进行权衡,以确定预期的投资回报。

9 总结

本系列文章,我们展示了一个发现之旅,并提供了对单元化架构的许多关键方面的全面概述和深入分析,以及将这种方法应用于现有和新架构的实用建议。

关注我,紧跟本系列专栏文章,咱们下篇再续!

作者简介:魔都架构师,多家大厂后端一线研发经验,在分布式系统设计、数据平台架构和AI应用开发等领域都有丰富实践经验。

各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。

负责:

  • 中央/分销预订系统性能优化
  • 活动&券等营销中台建设
  • 交易平台及数据中台等架构和开发设计
  • 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
  • LLM Agent应用开发
  • 区块链应用开发
  • 大数据开发挖掘经验
  • 推荐系统项目

目前主攻市级软件项目设计、构建服务全社会的应用系统。

参考:

  • 编程严选网

本文由博客一文多发平台 OpenWrite 发布!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/73941.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

springboot3.0自动配置

目标 本文主要介绍springboot3.0是如何创建一个可以进行自动配置的jar包的 自动配置的定义是,一个jar包里面定义了一些spring的bean,当导入这个jar包的时候会自动将这些bean导入进去 方法 创建 AutoConfiguration.imports 文件 创建目录 META-INF/spring/org.springframework…

java 常见异常,及解决方案

异常体系图常见异常: 1、NullPointerException 空指针异常:访问一个空对象的属性或者方法时会出现 解决:提前进行判空处理 2、IOException IO流异常:IO,即:input, output,在读写磁盘文件、网络内容的时候经常会生的一种异常 解决:捕获 IOException 并处理或重新抛出 3、…

简单使用pyinstaller

pyinstaller介绍 PyInstaller 用于将 Python 程序打包成独立的可执行文件(EXE),以便于在没有 Python 环境的计算机上运行。 -F参数 -F 参数是 PyInstaller 的一个简写,用于生成单个可执行文件。它与 --onefile 参数的作用相同。当使用 -F 参数时,PyInstaller 会将所有依赖…

Codeforces Round 980 (Div. 2)

糖丸了,什么沟史比赛 A.Profitable Interest Rate初始有 \(a\) 个硬币,可以花费硬币开通盈利账户与非盈利账户开通盈利账户需要至少花费 \(b\) 个金币 开通非盈利账户没有限制 每在非盈利账户花费 \(x\) 元,盈利账户的限制 \(b\) 就减少 \(2x\) 元求最大的在盈利账户上的花费…

黑马JavaWeb-day01

Web:全球广域网,也称为万维网(www World Wide Web),能够通过浏览器访问的网站。 web网站的工作流程:网页由哪些部分组成:文字、图片、音频、视频、超链接 我们看到的网页背后的本质:前端代码 前端代码是如何转化成用户眼中的网页?:通过浏览器的解析和渲染转化成用户看到…

count(*)、count(1)哪个更快?面试必问:通宵整理的十道经典MySQL必问面试题

一、你是如何理解Count(*)和Count(1)的? 这两个并没有区别,不要觉得 count() 会查出全部字段,而 count(1) 不会。所以 count() 会更慢,你觉得 MySQL 作者会这么做吗? 可以很明确地告诉你们 count() 和 count(1) 是一样的,而正确有区别的是 count(字段)。如果你 count() 的…

重构案例:将纯HTML/JS项目迁移到Webpack

我们已经了解了许多关于 Webpack 的知识,但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后,就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构,项目位于 GitHub 上,非常感谢该项目的贡献者。…

最小体积拉取git仓库并保持可更新

对于超大型的git 仓库不需要提交只是拉取代码进行查看并希望保持代码更新,那么使用depth不仅能得到极小体积的仓库还能大大提速拉取时间对于超大型的git 仓库不需要提交只是拉取代码进行查看并希望保持代码更新,那么使用depth不仅能得到极小体积的仓库还能大大提速拉取时间 拉…