对于“软件架构”这个词有很多定义和含义。而且,“软件开发”、“软件设计”和“软件架构”这三个概念之间存在相当大的重叠,它们在许多方面相互交融。
从核心上看,可以将软件架构视为在构建应用程序时,对不同选择进行权衡的学科。
1 为什么需要权衡以及我们为什么在意?
我们在构建软件时必须进行权衡的原因,与其他学科中的权衡原因相同。计算系统是复杂的,复杂性越高,实现特定系统的全部目标的方式就越微妙。这些目标:
- 既可以是功能性的(例如提供用户自助服务的能力、处理特定事件、接受某些输入并产生输出)
- 也可以是非功能性的(例如每秒处理数百万个请求、实现零信任安全、提供100毫秒以下的响应时间)
如金融投资中,人们普遍理解风险与收益之间的权衡。投资越风险,潜在的财务回报越大。投资越安全,预期收益就越小。
同样的规则也适用于计算,特别是在设计分布式应用程序时。许多组织遇到的问题不是他们必须做出某些让步或权衡,而是大多数组织要么对自己所做的权衡不了解,要么缺乏系统的、明确的和有效的方法来进行这些权衡。
本“架构权衡”系列的目的是阐明在软件架构的不同原则之间进行权衡时的决策过程以及此类决策的具体技术影响。
2 我们在权衡什么?
如上所述,大多数与系统和应用程序架构相关的决策都涉及某种程度的权衡。
既然我们已经知道为什么需要讨论、权衡和有意识地思考架构权衡,我们可以谈谈我们实际在系统和应用程序中进行权衡的方面。
这些架构权衡有时分为两大类:
- 系统的基本架构特性有关(如可扩展性与简洁性)
- 与具体技术、机制和架构风格有关(如同步通信与异步通信、Kafka与消息总线等)。前者更为广泛的权衡类别也决定了更具体的权衡
本文重点讨论第一类架构权衡——基础架构特性。
因此,当我们谈论架构权衡时,我们实际上是在讨论我们希望支持哪些架构特性并将其纳入我们的主要目标。另一方面,我们也在识别那些我们有意识地决定不太关注或完全放弃的架构特性,以便更加重视那些我们认为更重要的特性。
下面是一些架构特性和一些常见的权衡场景。
3 架构特性
当谈论系统或应用程序架构的固有或基础特性时,我们实际上是指一组关键属性,这些属性定义了特定的系统或应用程序。以下是这些特性的一小部分示例。这绝不是一个详尽的列表,还有许多其他的架构特性。
- 可扩展性
- 可观测性
- 可审计性
- 弹性
- 响应性
- 可测试性
- 互操作性
- 可维护性
- 可支持性
这些特性有时被称为“系统属性”、“架构属性”或干脆称为“后缀-ility”属性。
这些系统特性或属性乍看之下似乎是独立的,但实际上,它们中的许多是相互交织的,可能有直接或反向关系。
4 互操作性 vs 可扩展性、弹性和响应性
让我们以互操作性为例。为了使系统具备互操作性,它需要能够轻松地与其他系统进行交互和通信。这通常意味着所有这些系统都需要使用通用协议。它们需要使用共同商定的标准,并且这些标准还需要设计得易于将来的系统也能相对轻松地“插入”到这种通信中。
然而,如果一个系统优先考虑互操作性,这很可能会影响系统的可扩展性。
举个具体的例子,假设现有的应用程序使用REST协议(依赖HTTP)进行通信。假设我们要引入一个新系统。为了使这个新应用程序与现有的应用程序互操作,我们决定该应用程序的所有进出通信都通过REST/HTTP进行。这看起来很合理。
然而,如果将新系统的通信限制在依赖HTTP上,可能会限制其响应能力和可扩展性,尤其是在需要处理大量请求的情况下。假设这个新系统需要每秒处理数百万个请求,并且是异步的(即调用者无需等待应用程序确认其已处理请求)。这种情况下,由于需要异步通信且Kafka协议(理论上)比HTTP开销更小,这种场景可能更适合使用事件驱动技术如Kafka。
换句话说,在这种情况下,互操作性与响应性以及可扩展性呈反比关系。
5 简单性、易上手性和可支持性 vs 响应性
另一个可能不太技术性、更具组织性的权衡发生在决定以易于支持作为主要架构驱动因素时。这可能意味着使用技术团队熟悉的技术。这也可能意味着使用行业内广泛使用和已知的技术和范式,以便新团队成员可以更快更高效地上手。
将可支持性作为首要任务听起来是显而易见的,因为谁不想要一个易于理解、支持并且易于向新开发人员介绍的系统呢?然而,仍然存在成本和权衡。
基于技术或范式的选择是否为大量专业人员所熟知,可能会阻碍架构的许多其他特性。可扩展性、响应性、弹性、可用性、安全性以及系统的许多其他方面很可能会被放在第二位。
例如,考虑需要设计一个处理和存储交易性和强关系数据的金融应用程序。假设实施该应用程序的团队熟悉NoSQL数据存储如MongoDB。虽然MongoDB是一个适合松散关联的文档型数据的优秀选择,但它不适合具有严格和复杂关系的数据。
对于不同实体之间具有复杂关系且需要临时复杂查询来检索这些数据的数据,通常不太适合像MongoDB这样的存储。这类数据通常更适合“传统”的关系数据库如Postgres或MySQL。
如果我们将可支持性作为这个应用程序的主要架构驱动因素,最终很可能会导致应用程序失败,并引发一系列挑战,最终导致应用程序完全无法扩展,数据库成为瓶颈(这是常见的问题)。
6 可维护性 vs 弹性和容错性
一般而言,系统越简单、移动部件越少,越容易维护。使用的技术和部署环境越少,系统运行和维护的速度和难度越低。
例如,在托管云运行服务中运行单实例应用程序要比分布在不同节点、不同集群、云区域和地区的分布式集群应用程序更容易维护。一些组织甚至通过跨多个云环境部署其系统来确保业务连续性、容错性和灾难恢复(迅速流行但有些争议的多云模式)。
由于每个云(Azure、AWS、GCP、IBM、Oracle等)提供商都有一套独特的功能、部署模型和机制,在多个云上维护一组应用程序成为一个显著挑战(通常是无法维持的)。
7 找到平衡点
上述的三个架构权衡示例可能更偏向极端情况。然而,它们代表了许多团队和组织在规划和选择正确的架构权衡路径时所面临的一些非常现实的挑战。
好消息是,您不必在二者之间做出选择。软件架构权衡以及软件开发的现实要更加复杂,实际上是一个选择的渐变。在这里,您可以选择在一定程度上实现可扩展性,同时在一定程度上实现简单性和互操作性。
关键在于如何找到不同架构特性之间的平衡,以及如何做出知情的、有意识的选择。
8 有意识地了解架构权衡
如我们在开头所说,许多,甚至可以说大多数组织,都是无意识地做出权衡。这往往导致这些组织做出错误的权衡,给其业务和底线带来长期且不利的影响。
依赖数字系统的企业必须有一个适当的计划和流程来做出软件架构和技术决策以及权衡。在没有建立正确的架构权衡意识的情况下,这些组织承担着不合理的风险,其影响和可能显著减缓组织进展的概率很大,在最坏的情况下甚至可能造成无法修复的损害。
接下来的部分将讨论如何进行架构权衡的推理和规划,以及一些具体和常见的情况。
关注我,紧跟本系列专栏文章,咱们下篇再续!
作者简介:魔都技术专家,多家大厂后端一线研发经验,在分布式系统、和大数据平台设计等方面有多年研究和实践经验,拥有从0到1的大数据平台和基础架构研发经验,对分布式存储、数据平台架构、数据仓库等领域都有丰富实践经验。
各大技术社区头部专家博主。具有丰富的引领团队经验,深厚业务架构和解决方案的积累。
负责:
- 中央/分销预订系统性能优化
- 活动&优惠券等营销中台建设
- 交易平台及数据中台等架构和开发设计
- 车联网核心平台-物联网连接平台、大数据平台架构设计及优化
目前主攻降低软件复杂性设计、构建高可用系统方向。
参考: