我们要权衡什么以及为什么要权衡?
我们所说的“软件架构”有很多定义和含义。构成“软件开发”、“软件设计”和“软件架构”的内容之间也存在相当大的重叠,因为这三个概念在许多方面融合在一起。
从本质上讲,它有助于将软件架构的学科视为在我们以这种或那种方式构建应用程序时做出的选择所产生的权衡之间做出有意识选择的学科。
为什么会有权衡,我们为什么关心?
我们在选择如何构建软件时必须进行权衡的原因与我们在其他学科中进行权衡的原因相同。计算系统很复杂,复杂度越高,我们为特定系统实现全方位目标的方式就越微妙。这些目标可以是功能性的(即为用户提供自助服务、处理特定事件、接受一些输入和产生输出的能力)也可以是非功能性的(即每秒处理数百万个请求的能力,实现零信任安全性) ,低于 100 毫秒的响应)。
例如,在金融投资中,对风险和回报之间的权衡有着内在的理解。一项投资的风险越大,其潜在的经济回报就越大。投资越安全,我们可以从该投资中预期的收益就越小。
同样的规则也适用于计算——尤其是在构建分布式应用程序时。许多组织遇到的问题不是他们必须做出某些让步或权衡。问题在于,大多数组织要么没有意识到他们正在做出的权衡,要么缺乏系统、清晰和有效的方法来进行这些权衡。
这个“架构权衡”系列的目的是在涉及到软件架构的不同原则之间的权衡以及此类决策的具体技术含义时,阐明决策过程。
我们在权衡什么?
正如我们在上面看到的,与您的系统和应用程序架构相关的大多数决策都涉及某种程度的权衡。
既然我们知道为什么架构权衡是需要讨论、权衡和有意识地推理的事情,我们就可以谈谈我们实际上在权衡系统和应用程序的哪些方面。
这些架构权衡有时分为两大类。第一个与关于系统的基本架构特征(即可扩展性与简单性)的决策有关。第二个与更具体的技术、机制和架构风格(即同步通信与异步、Kafka 与消息总线等)的决策有关。前者,更一般的权衡类别,也决定了更具体的权衡。
在本文中,我们将重点关注第一类架构权衡——即基础架构特征。
因此,当我们谈论架构权衡时,我们实际上是在谈论我们想要支持哪些架构特征并将其纳入我们的主要目标。硬币的另一面是,我们也在识别那些我们有意识地决定较少关注或完全放弃的架构特征,以支持我们认为更重要的那些特征。
下面是几个架构特征和一些常见权衡方案的示例。
架构特点
在谈论系统或应用程序架构的固有或基础特征时,我们实际上指的是表征特定系统或应用程序的关键属性的集合。以下是这些特征的一小部分作为示例。无论如何,这不是一份详尽的清单。还有许多其他的架构特征
- 可扩展性
- 可观察性
- 可审计性
- 弹力
- 响应能力
- 可测试性
- 互操作性
- 可维护性
- 可支持性
这些特征有时被称为“系统属性”、“架构属性”或通常简称为“ilities”。
乍一看,这些系统特征或属性似乎彼此独立。但实际上,它们中的许多都非常交织在一起,可以具有直接或反向的关系。
互操作性与可扩展性、弹性和响应性
让我们以互操作性为例。为了使系统具有互操作性,它需要能够轻松地与其他系统交互和通信。这通常意味着所有这些系统都需要使用通用协议。他们需要使用共同和商定的标准,这些标准的构建方式也使得未来的系统也可以相对轻松地“插入”到该通信中。
但是,如果互操作性是系统的优先事项,那么这很可能会影响系统的扩展能力。
要将这一切归结为一个具体示例,请考虑一个场景,您有一些使用 REST 协议(依赖于 HTTP)进行通信的现有应用程序。假设我们正在引入一个新系统。为了使这个新应用程序可以与现有应用程序互操作,我们决定这个应用程序的所有入站和出站通信也将通过 REST/HTTP 完成。这似乎是有道理的。
但是,如果您的新系统需要处理大量请求,则将您的新系统限制为依赖于 HTTP 的通信可能会限制其响应能力和可扩展性。想象一下,这个新系统必须每秒处理来自该调用者的数百万个请求,并且也是异步的(即调用者不需要等待应用程序确认它已经处理了请求)。由于对异步的要求以及专有的 Kafka 协议(至少在理论上)比 HTTP 的开销更少,因此这种情况可能更适合 Kafka 等事件驱动技术。
换句话说,在这个特定场景中,互操作性与响应能力和可扩展性成反比关系。
简单、易于上手和可支持性与响应性
在决定将相对容易支持的架构作为主要架构驱动程序时,可能会发生另一个技术性更少但组织性更强的权衡。这可能意味着使用组织内技术团队熟悉的技术。这也可能意味着使用业内广为人知和使用的技术和范式,以便新的团队成员可以更快、更高效地开始使用它们。
将可支持性作为首要任务听起来很容易,因为谁不想要一个易于理解、支持和介绍给新开发人员的系统?不过,与往常一样,存在成本和权衡。
根据大量专业人士所了解的技术或范式来选择它们可能会阻碍我们架构的许多其他特征。系统的可扩展性、响应性、弹性、可用性、安全性和许多其他方面很可能会排在第二位。
例如,考虑一个需要设计一个需要处理和存储事务性和强关系数据的金融应用程序的情况。假设实现此应用程序的团队熟悉 MongoDB 等 NoSQL 数据存储。现在,虽然 Mongo 是松散相关文档类型数据的绝佳选择,但它并不适合具有严格和复杂相互关系的数据。
不同实体具有复杂关系以及需要临时复杂查询来检索该数据的数据通常不适合 Mongo 之类的东西。这种类型的数据通常更适合“传统”关系数据库,例如 Postgres 或 MySQL。
如果我们将可支持性作为这个应用程序的主要架构驱动因素,它很可能会设置应用程序以防万一,并会引入一系列挑战,最终导致应用程序完全无法扩展,并且数据库成为一个展示 -塞子瓶颈(通常是这样)。
寻找平衡
上述架构权衡的三个示例可能更多地涉及极端情况。然而,它们代表了许多团队和组织在规划和选择正确的架构权衡导航过程中面临的一些非常现实的挑战。
好消息是您不一定非要选择其中之一。软件架构权衡和一般软件开发的现实要微妙得多,并且确实代表了选项的梯度。例如,您可以在此处选择具有一定程度的可扩展性,同时具有一定程度的简单性和互操作性。
关键是要知道如何在不同的架构特征之间找到平衡,并知道如何对这些特征做出明智的、有意识的选择。
有意识并意识到架构权衡
正如我们在开始时所说的,我敢说,许多组织——大多数组织都会无意识地选择权衡取舍。这通常会导致这些组织做出错误的权衡,这对他们的业务和底线产生长期且有害的影响。
由数字系统驱动的企业必须制定适当的计划和流程来制定软件架构、技术决策和权衡。如果没有围绕架构权衡建立适当的意识,这些组织会承担不合理的风险,其影响和可能性都很大,在最好的情况下会显着减慢组织的进度,在最坏的情况下会损坏到无法修复的程度。
下一部分将讨论这一点——如何为架构权衡以及一些特定和常见的情况进行推理和规划。