信息太多等于没有信息或者,正如他们所说,不记得的事情从未存在过。软件和系统架构的模式多达数千种。没有人知道所有模式,也没有人想知道(如果你说你知道,你一定已经读过程序模式语言档案。你读过吗?我也没有)。
每年仅在会议上就会产生数百种模式,更不用说书籍和软件工程网站了。旧模式被重新包装或遗忘和重新发明。
软件架构和系统架构中模式名称的差异尤其如此。新的N 层是引擎盖下的旧层,不是吗?
这破坏了引发模式炒作的最初想法:
- 模式是一种无处不在的语言。如今,类似的模式(即使不是完全相同的)都有不同的名称,其中一些模式太晦涩难懂,甚至从未听说过(请参阅PLoP 档案)。
- 模式是知识传递的载体。如果旧模式被重新发明或剽窃,大部分旧知识就会丢失。经验没有连续性。
- 模式语言是架构师的终极工具。随着模式的重新发明,模式语言也在不断更新。我们最多只能拥有特定领域或架构受限(DDD、微服务)的模式系统。没有老一辈模式爱好者承诺提供的统一愿景。
我们被愚弄了吗?
结论 比较防火墙和响应缓存。两者都向用户代表一个系统,并实现系统行为的通用方面。两者都是代理。 以Saga Execution Component和API Composer为例。两者都是高级服务,它们对底层系统进行一系列调用 — 它们对其进行编排。两者都是编排器。
就这么简单,我们可以对架构模式进行分类。
元模式 有没有办法让这些模式井然有序?它们太多了,有些晦涩难懂,有些又过于专业化。
我们可以尝试。在一个子集上。这个子集应该是:
- 对于大多数程序员来说,这非常重要。
- 小到可以存入人的记忆或书中。
- 足够完整以确保我们不会错过任何关键内容。
有这样的一套吗?我相信有。
架构模式 [POSA1]定义了三类模式:
- 处理系统的整体结构及其组件的功能的架构模式。
- 描述对象之间关系的设计模式。
- 在给定的编程语言之上提供抽象的习语。
任何系统都有内部结构。当其开发人员谈论“架构风格” [POSA1] 或绘制结构图时,通常归结为两个或三个众所周知的架构模式的组合。选择架构模式作为我们研究的主题,让我们能够从大量反复描述类似设计的书籍和文章中汲取灵感。
此外,一旦系统不遵循最新潮流,它就会被广泛宣传为新颖之物(或其设计者被贴上过时和目光短浅的标签),因此我们可以期望听说过几乎所有在实践中使用的架构。
为了组织一组模式,我们依赖于以下概念
设计空间 设计空间[POSA1、POSA5] 是一种为构建系统时做出的每个选择分配一个维度的模型。因此,它包含了设计系统的所有可能方式。唯一的问题是它是多维的,可能是无限的,而且维度因系统而异。
有一个解决方法——我们可以使用从设计空间到我们更习惯的二维或三维空间的投影。然而,投影会丢失信息。与直觉相反,这对我们有好处——相似的架构在细节上有所不同,一旦它们不同的维度消失,它们就会变得相同。如果我们只能找到 2 或 3 个最重要的维度,它们同样适用于我们想要研究的集合中的每个模式,那就是涵盖所有已知系统设计的架构模式。
结构定义架构 系统往往具有内部结构。那些没有内部结构的系统因其特殊属性而被贬称为“大泥球”。结构就是模块、模块角色和交互。许多架构风格(例如层或管道)都是以其结构命名的,而其他架构风格(例如事件驱动架构)则突出了其某些方面,暗示结构定义了系统的主要属性。
我不是第一个得出这种结论的人。
元模式(具有相似结构的模式集群)是在第一批设计模式出现后不久定义的,但它们从未对软件工程产生持久影响。我认为这种方法过早地应用于分析 [GoF] 模式,这使得设计模式子集非常随机和不完整,导致过度概括。我打算绘制整套架构模式的结构,将具有相同结构的模式组合在一起(产生元模式),绘制元模式之间的关系,并可能展示系统的结构如何定义其属性。
对于一本小书来说,这是一个相当雄心勃勃的计划,不是吗?
我们的架构模式集仍然不完整,也不小,而且,结构图的绘制方式因来源而异——除非我们建立一个通用的坐标系
发明一个通用的坐标系统来适应任何模式的表示,从迭代器到半同步/半异步,可能太难了,但我们肯定能为架构模式找到一些东西,因为它们都共享范围,即整个系统。系统的实现通常会沿着哪些维度来绘制?
- 抽象性——既有高级业务逻辑,也有低级细节。一个高度抽象的操作会展开成许多低级操作:Python 脚本在 C 运行时和汇编驱动程序之上运行;编排器调用服务的 API 方法,服务本身会针对其数据库运行 SQL 查询,而数据库充满了低级计算和磁盘操作。
- 子域— 任何复杂系统都会管理多个子域。操作系统需要处理各种外围设备和协议:视频卡驱动程序与 HDD 驱动程序或 TCP/IP 堆栈几乎没有相似之处。企业有多个部门,每个部门都运行符合其需求的软件。
- 分片——如果部署了模块的多个实例,并且该事实是架构的一个组成部分,那么我们应该在结构图上表示多个实例。
我们将
- 垂直绘制抽象轴,将高级模块放置在图的上方,
- 水平绘制子域轴,对角绘制分片轴。
映射和缩减 现在我们有了似乎适合任何架构模式的通用坐标,我们可以开始将我们的架构模式集映射到该坐标系中——将多维设计空间缩小到我们正在寻找的几个结构图维度的过程。然后,在过滤掉细节之后,我们发布的一百多个模式应该会产生一些几何等效图簇——因为很少有简单的系统可以在重复之前在平面上绘制出来。每个簇都将代表一个架构元模式——具有类似结构和功能的架构模式的概括。
这意味着什么 化学得到了元素周期表。生物学得到了生命之树。本书致力于为软件和系统架构构建类似的东西。
您可能会说“这毫无意义!化学和生物学是经验科学,而软件架构不是!”是吗?
架构元模式列表
前面阐述了元模式背后的理论——具有相似结构和属性的架构模式集群。简
基本元模式 基本元模式既是广泛使用的独立架构,也是更复杂系统的构建块。它们包括单组件整体架构及其沿每个坐标轴(抽象性、子域和分片)划分的结果:
1、整体式 Monolith单体 是单组件系统,是最简单的架构。它易于编写,但难以发展和维护。 包括:Reactor、Proactor、Half-Sync/Half-Async。
2、碎片 分片是单体的多个实例。它们可以扩展,但通常需要外部组件进行协调。 包括:实例、单元(亚马逊定义);分片、按需创建、池。
3、层 每个抽象层包含一个组件。各个层可能在技术、力量和规模上有所不同。 包括:多层架构。
4、服务 服务按子域划分系统,通常会导致将大小相当的部分分配给专门的团队。但是,服务系统很难同步或调试。 包括:领域服务;基于服务的架构、模块化整体(Modulith)、微服务、设备驱动程序、参与者。
5、管道 Pipeline 是一种单向流动的服务。每个服务都实现单个请求处理步骤。系统灵活,但可能会失控。 包括:管道和过滤器、编排事件驱动架构、纳米服务。 扩展元模式 这些模式通过提供系统行为的一个或两个方面并通常将其他组件粘合在一起的层来扩展服务、分片甚至整体。
6、中间件 中间件是实现系统组件实例之间通信的一层,也可以管理这些实例。这样,每个实例就无需跟踪它所处理的其他实例。 包括:(消息)代理、部署管理器。
7、共享存储库 共享存储库存储系统数据,通过事务维护其完整性,并可能支持订阅数据子集的变更。这样,其他系统组件就可以专注于实现业务逻辑。 包括:共享数据库、黑板、基于空间架构的数据网格、共享内存、共享文件系统。
8、代理人 代理在系统和客户端之间进行调解,透明地处理一些通用功能。 包括:防火墙、响应缓存、负载均衡器、反向代理、适配器。
9、编排器 编排器将用例实现为对底层组件的调用序列,而这些调用序列通常彼此不知道彼此的存在。 包括:工作流所有者、应用层、外观、中介;API 编写器、流程管理器、Saga 执行组件、集成(微)服务。
多功能组件 有几种模式结合了两个或多个扩展层的功能。 包括:消息总线、API网关、事件中介、企业服务总线、服务网格、基于空间架构的中间件。
碎片化的元模式 有些模式没有系统范围的层。其中一些模式在不同的抽象级别上合并了两个或三个域,因此一个域中的服务(仅限于子域)充当另一个域的层。
10、分层服务 分层服务是一个总括元模式,它强调服务或管道的实现细节。 包括:编排的三层服务、编排的两层服务、命令查询责任分离(CQRS)。
11、多语言持久性 多语言持久性是指使用角色或技术不同的多个数据存储。每个上层组件都可以访问任何数据存储。每个数据存储都是一个共享存储库。 包括:专用数据库、私有和共享数据库、数据文件、内容分发网络(CDN);只读副本、报告数据库、内存映像、查询服务、搜索索引、历史数据、Cache-Aside。
12、前端的后端 前端后端为每种类型的系统客户端提供一项服务 (BFF)。BFF 可以是代理、编排器或两者兼而有之。每个 BFF 与其下属的所有组件进行通信。该模式看起来像是部署在一起的多个代理或编排器。 包括:分层微服务架构。
13、面向服务的架构 SOA 有三到四层服务,每层都有自己的域。上层包含编排器,这些编排器通常是特定于客户端的,如 BFF。第二层包含业务规则,并按业务子域划分。下层是库和实用程序,按功能和技术分组。每个组件都可以使用(编排)其下方的所有组件。 包括:分段式架构;分布式整体式架构、企业 SOA。
层次结构 一些领域允许分层组合,其中功能分布在组件树上。 包括:编排器的编排器、总线的总线、基于单元的(微服务)架构(WSO2 版本)(服务的服务)。
实施元模式 组件的内部结构出现了几种模式。
14、插件 插件模式旨在将主逻辑与系统行为的可自定义细节分开。这样,同一代码便可用于多种风格或客户。 包括:插件架构、附加组件、策略、挂钩。
15、六边形架构 六边形架构是插件的一种专业化,其中每个外部依赖项都被隔离在适配器后面,因此易于更新或替换。 包括:端口和适配器、洋葱架构、清洁架构;模型-视图-控制器(MVC)。
16、微内核 这是插件的另一种衍生,具有一个基本的核心组件,用于在资源消费者(应用程序)和资源提供者之间进行协调。微内核是应用程序的中间件,也是提供者的协调器。 包括:操作系统、软件框架、分布式运行时、解释器、配置文件、saga引擎、AUTOSAR经典平台。
17、Mesh Mesh由相互通信的分片组成,每个分片可托管一个应用程序。分片构成一个容错分布式中间件。 包括:网格;对等网络、叶脊架构、参与者、服务网格、基于空间的架构。