读 | Software Architecture Patterns

news2024/12/23 23:53:37

个人博客

Software Architecture Patterns》是 Mark Richards 2015 年出的一本小册子,对常用的架构模式进行了一个简单梳理,书中列了 5 种:

  • 分层(Layered)
  • 事件驱动(Event-Driven)
  • 微内核(Microkernel)
  • 微服务(Microservices)
  • 基于空间(Space-Based)

Mark Richards 后续又出了两本书,《Fundamentals of Software Architecture》、《Software Architecture: The Hard Parts》——参见 读后感。

Layered Architecture

单体架构,将应用这个整体分解为不同的层次,在不同的层次处理不同的问题,即关注点分离原则的一种实际运用。在社会生活的各方面同样可以观察到对该原则的广泛运用,比如组织中的科层制——总经理就不会去厂房打螺丝。软件设计的这种原则往前追溯,可能就借鉴自人们在社会生活中长期实践所总结出的经验。

分层架构在网络中得到了最成功的运用——OSI 分层模型(OSI 模型发展过程中遇到的问题及其解决方案,对其他运用分层思维解决问题的领域具有良好的借鉴意义),在 Web 应用中也广为人知,常用的 MVC 架构即是把应用分解为 模型-视图-控制器 三层,模型层对接业务模型,视图层对接用户界面展示,控制器层居中粘合模型和视图。

典型的 Web 分层架构包括 4 层:

  • 表现层,负责界面展现,面向 PPT 的说法叫负责人机交互接口;
  • 业务层,负责实现业务逻辑;
  • 持久层,负责把数据持久化,掉电不丢失;
  • 数据库层,应用使用的数据库。
    在这里插入图片描述

请求必须沿着一定的方向逐层传递,不能跨层——每一层都是 closed 的,这样做的好处是隔离了变化,某一层的变化只影响相邻层,而不会影响其他层。特殊情况下,某层也可以设置为 open —— 即允许被跨越。

总评价:

  • 全局敏捷性,低,单体本质上不能快速响应变化,同时各组件可能紧耦合在一起;
  • 易部署性,低,设计不良的情况下一个小的改动需要重新部署整个应用;
  • 易测试性,高,因为严格分层,所以可以方便地进行 mock/stub;
  • 性能,低,请求必须经过所有层,而可能在某些层没有处理逻辑;
  • 易伸缩性,低,扩展时需要进行整层扩展或整个应用整体扩展;
  • 易开发性,高,该架构广为人知且团队组织架构通常也分为了前端/后端/DBA,可以很好地映射并组织工作。

Event-Driven Architecture

大多数的应用是请求响应式的,而事件模型是获取相应事件并采取相应的行动。事件驱动架构是一种分布式异步架构,具有高可扩展性。

事件驱动架构有两种拓扑:中介拓扑、代理拓扑。

中介拓扑(mediator topology)

由中介来规划事件应该发送到哪些事件处理器,从而控制整个事件处理过程,如 BPM 业务流程流转。

架构组件包括:

  • 初始事件,启动整个事件过程的事件;
  • 事件队列,存放初始事件的队列;
  • 事件中介,核心组件,负责编排整个处理过程,根据掌握的事件处理步骤生成事件,并发送到对应的事件通道,可以根据领域不同划分出多个;
  • 事件通道,存放(需要事件处理器处理的)事件,通常也是队列;
  • 事件处理器,监听事件通道,处理事件,并向中介返回已完成事件处理的响应,不会告知对系统其他部分做了什么。
    在这里插入图片描述

简单的事件中介有 Spring Integration、Apache Camel、Mule ESB,复杂的有 Apache ODE、Oracle BPEL。一种具体的使用方式是将事件分为简单/复杂/困难,每个事件都通过一个简单事件中介,简单事件中介查询事件分类来决定是自己处理还是委托给更复杂的事件中介。

代理拓扑(broker topology)

没有一个中心,使用轻量级消息中间件来充当各个事件处理器的事件代理,如 RabbitMQ、ActiveMQ、HornetQ 等。

架构组件包括:

  • 初始事件,启动整个事件过程的事件;
  • 事件代理,轻量级消息中间件,一般采用发布-订阅模式;
  • 事件处理器,监听并处理事件,生成待处理事件发布到事件代理;
  • 待处理事件,等待事件处理器处理的事件。
    在这里插入图片描述

相比于中介拓扑,代理拓扑没有一个中心组织者,只有各自独立的参与者,但参与者会在传播介质(事件代理)中广播自己对系统做的改动,由其他参与者根据事件做出自己的反应。

因为事件驱动架构是分布式的,所以也需要考虑分布式架构所面临的问题,如对端的可用性、响应性、重连等。另外,从架构本身来说也有两个困难:缺乏原子事务、各事件处理器之间的契约(事件具有自己的结构)的创建、维护和管理。

总评价:

  • 全局敏捷性,高,各事件处理器相互独立,耦合性低,变化的影响被局限在一个有限的范围;
  • 易部署性,高,各事件处理器相互独立,耦合性低,物理分开方便单独部署;
  • 易测试性,低,一个案例需要考虑若干事件、若干组件;
  • 性能,高,异步带来高性能;
  • 易伸缩性,高,各组件独立;
  • 易开发性,低,异步增加复杂性以及架构复杂后带来的更多的错误类型。

Microkernel Architecture

微内核架构一般又称为插件架构,是一种单体架构,架构组件包括:

  • 核心系统,系统运行的最小功能集;
  • 插件,独立组件,用于扩展系统功能,可以方便地插拔。
    在这里插入图片描述

插件和核心系统之间的通信通常是点对点的,插件之间相互隔离,只和核心系统交互。插件可以是基于编译的,也可以是基于运行时的。

一个关键问题是:核心系统如何发现插件

常见方案是通过一个注册中心,在注册中心中存放插件的信息,包括名称、数据契约、远程访问协议细节。对于核心系统和插件之间的契约,一般是跨插件域的标准契约,包括从插件返回的行为、输入数据、输出数据。

插件要接入核心系统,可以通过多种方式,如 OSGi、消息、REST 等。某种程度上,博主当前负责的系统也是一个微内核架构,通过动态注册服务来扩展系统的能力。

微内核架构和开源思想可以说是天作之合,这种架构天然鼓励社区参与,对于商业初创产品来说也是合适的——先聚焦核心功能,再逐步推出扩展功能。不只 Linux、Eclipse、Vscode、Nginx 等软件界的明星项目,这种架构思想在硬件架构中也是通用的,继续扩大观察面会发现生活中遍布这种设计思想。

总评价:

  • 全局敏捷性,高,插件隔离性好,可以快速变化;
  • 易部署性,高,支持运行时部署,停机时间极大缩短;
  • 易测试性,高,插件互相独立;
  • 性能,高,可以只启用需要的功能;
  • 易伸缩性,低,还是单体架构;
  • 易开发性,低,契约版本管理、插件注册、插件粒度、接入方式带来更大的复杂性。

Microservices Architecture

留白,春节再续…

Space-Based Architecture

以传统的 Web 应用为例,在面对大并发量时,第一个迎接流量洪峰的是 Web 服务器,可以很容易地横向扩展;往下来到应用服务器,应用服务器稍微复杂一点,也可以扩展;最后,洪峰来到了数据库,对数据库做横向扩展通常比较困难。也就是说,最后是数据库的并发事务处理能力,决定了整个系统的最大并发处理能力。当然也可以通过提前的分库分表,通过 apache-sharding 之类的方式来支持更大的并发能力,但从架构上说,难以灵活应对极端并发场景的缺陷是天生的。

于是有了基于空间的架构模式:通过删除中央数据库作为系统中的同步约束,代之以利用复制的内存数据网格,来实现高可伸缩性、高弹性和高性能。

架构组件包括:

  • 处理单元,通常包含程序逻辑、内存数据网格、复制引擎;
  • 虚拟化中间件,核心组件,负责管理数据同步和请求处理,包含消息网格、数据网格、处理网格和(管理处理单元的)部署管理器。
    在这里插入图片描述

虽然在该架构中不再要求有一个中央数据库,但还是可以增加一个,作为初始化加载数据时的来源,和异步持久化数据时的地方。

总评价:

  • 全局敏捷性,高,快速响应负载,应用小也可以快速响应代码变更;
  • 易部署性,高,借助工具;
  • 易测试性,低,要模拟这种架构提供的易伸缩性和弹性比较复杂;
  • 性能,高,基于内存和缓存机制;
  • 易伸缩性,高,没有中央数据库的约束;
  • 易开发性,低,架构复杂不便于理解,同时需要借助工具。

The End

各种架构模式并不是排他的,在实际使用时常常可以根据需要混合使用。

有模式,就有反模式,任何实际工作都不可能完美匹配模式场景,所以不能拘泥于理想的理论描述,而必须结合实际情况,在运用模式无法达到想要效果时进行必要的调整。

需要记住的是,调整一定有代价,架构设计就是权衡是否值得为了一个设计目标而在一定程度上放弃另一个目标。

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

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

相关文章

HTML的常见标签

什么是 HTML? HTML 是英文 Hyper Text Markup Language(超文本标记语言)的缩写,是一种用于创建网页的标准标记语言。 什么是HTML 标签? HTML 文档和 HTML 元素是通过 HTML 标签进行标记的 HTML 标签是由尖括号包围的关键词&am…

【阶段四】Python深度学习07篇:深度学习项目实战:循环神经网络的原理和结构

本篇的思维导图: 循环神经网络 循环神经网络,就是专门用于处理语言、文字、时序这类特征之间存在“次序”的问题。这是一种循环的、带“记忆”功能的神经网络,这种网络针对序列性问题有其优势。 循环神经网络的原理和结构 序列数据的概念 序列数据,是其特征的先后…

电路方案分析(十六)高效备用电源设计方案

高效备用电源设计方案 备用电源: 备用电源是一种在主电源发生故障时为负载提供紧急电源的电气系统。适当的备用电源通过提供存储在备用电容器或电池中的能量,提供即时保护,防止主电源中断而产生故障。这种备份电源通常用于保护硬件&#xf…

表单<form>

创建表单 <form> 标签用于创建供用户输入的 HTML 表单。 <form>标签的action属性的值指定了表单提交到服务器的地址。 <form> 元素包含一个或多个如下的表单元素&#xff1a; <input> <textarea> <button> <select> <option&g…

JAVA设计模式--行为型模式--职责链模式

1.责任链模式&#xff08;Chain of Responsibility Pattern&#xff09; 1.1介绍 为请求创建了一个接收者对象的链。这种模式给予请求的类型&#xff0c;对请求的发送者和接收者进行解耦。这种类型的设计模式属于行为型模式。在这种模式中&#xff0c;通常每个接收者都包含对…

C语言文件操作(一文带你吃透文件各种操作)

文章目录 一、为什么要使用文件 二、什么是文件 2、1 程序文件 2、2 数据文件 2、3 文件名 三、文件的打开关闭及读写操作 3、1 文件指针 3、2 文件的打开和关闭操作 3、3 文件的读写函数详解 3、3、1 fgetc、fputc函数详解 3、3、2 fgets、fputs函数详解 3、3、3 fscanf、fpri…

神经网络介绍-激活函数、参数初始化、模型的搭建

目录1、深度学习了解1.1 深度学习简介1.2 神经网络2、神经网络的工作流程2.1 激活函数2.1.1 Sigmoid/Logistics函数2.1.2 tanh&#xff08;双曲正切曲线&#xff09;2.1.3 RELU2.1.4 Leaky Relu2.1.5 SoftMax2.1.6 其他激活函数2.2 参数初始化2.2.1 随机初始化2.2.2 标准初始化…

【博客585】ipvs场景下dummy网卡的作用

linux ipvs模式下dummy网卡的作用 1、场景&#xff1a; 在使用ipvs来实现vip的负载均衡的时候&#xff0c;有时我们会在linux中创建一块dummy网卡&#xff0c;并在网卡上绑上vip 2、场景示例&#xff1a;k8s kube-proxy组件的ipvs模式 kube-proxy在ipvs模式下生成了一块kub…

iperf工具源码下载、编译、编译报错解决、以及测试网络带宽

1、iperf源码下载 (1)源码下载地址&#xff1a;https://iperf.fr/iperf-download.php; (2)有的版本源码下载下来并不能直接编译成功&#xff0c;可能会报缺少头文件或者编译选项的错误&#xff0c;要么去解决这些错误&#xff0c;要么换个版本再试一下&#xff1b; (3)在我的环…

Linux学习【教程+实操】【超基础】

链接:资料提取码&#xff1a;6klp 今日内容Linux简介Linux安装网卡设置安装SSH连接工具Linux和Windows目录结构对比Linux常用命令Linux命令初体验文件目录操作命令拷贝移动命令打包压缩命令文本编辑命令查找命令Linux软件安装软件安装方式安装jdk&#xff08;采用二进制发布包…

mysql索引字段设计

表字段数量与row大小限制可以参考官方文档 https://dev.mysql.com/doc/refman/8.0/en/column-count-limit.html#column-count-limits 复合索引 参考&#xff1a;https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html 数量限制 一个复合索引最多可以包含16个列&…

微信小程序--自定义组件

组件的创建与引用 1.创建组件 在项目的根目录中&#xff0c;鼠标右键&#xff0c;创建 components -> test 文件夹 在新建的components -> test文件夹上&#xff0c;鼠标右键&#xff0c;点击“新建Component" 键入组件的名称之后回车&#xff0c;会自动生成组件对…

C语言进阶(9)——C语言文件操作

本章重点 为什么使用文件什么是文件文件的打开和关闭文件的顺序读写文件的随机读写文本文件和二进制文件文件读取结束的判定文件缓冲区 文章目录本章重点1.为什么使用文件2.什么是文件2.1程序文件2.2数据文件2.3文件名3.文件打开和关闭3.1 文件指针3.2文件的打开和关闭4. 文件…

【蓝桥杯嵌入式】第十一届蓝桥杯嵌入式省赛(第二场)程序设计试题及其题解

题目再现 题目分析 通过阅读本届试题可知&#xff0c;其功能比较单一&#xff0c;除了试题中常客——LED、LCD、按键三巨头外&#xff0c;还包含了定时器的PWM以及ADC读取这两个部分&#xff0c;考察的重点在于对定时器产生PWM的应用以及如何修改PWM的占空比&#xff0c;完全消…

MPU-6000(6050)介绍

MPU-6000&#xff08;6050&#xff09;简介MPU-60X0是全球首例9 轴运动处理传感器。它集成了3 轴MEMS陀螺仪&#xff0c;3 轴MEMS加速度计&#xff0c;以及一个可扩展的数字运动处理器DMP&#xff08;DigitalMotion Processor&#xff09;&#xff0c;可用I2C接口连接一个数字传…

react PureComponent

这个 其实和我之前写的文章react组件优化&#xff0c;当父组件数据变化与子组件无关时&#xff0c;控制子组件不重新渲染实现的东西是一样的 只是用了一种更简洁的方式 我们还是重新来一次 创建一个react项目 然后 创建一个子组件 我这里就直接叫 subset.jsx 参考代码如下 i…

ADAM: A METHOD FOR STOCHASTIC OPTIMIZATION

核心 Adam: 一种基低阶矩的自适应估计的随机目标函数的一阶梯度优化算法&#xff0c;该方法实现简单**&#xff0c;计算效率高&#xff0c;内存需求很少**&#xff0c;对梯度的对角线重新缩放不变&#xff0c;并且非常适合于在数据或参数方面较大问题&#xff0c;该方法也适用…

ADI demo PS工程的编译-以adrv9371x_zc706为例子

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 ADI demo PS工程的编译-以adrv9371x_zc706为例子前言VITIS建工程总结前言 接《ADI demo PL工程的编译-以adrv9371x_zc706为例子之使用Cygwin》这篇。导出XSA文件&#xff0c…

VMware虚拟机搭建安装MacOS13及开发环境搭建

文章目录前言准备工作&#xff1a;安装虚拟机及MacOS系统1.安装VMware 虚拟机2. 运行解锁工具3. 安装macOS 134. 配置网络5. 安装VMware tools开发环境1. 安装xcode2. 安装HbuilderX前言 终于把macOS13虚拟机安装好了&#xff0c;比起上次安装macOS10,这次走了很多弯路。 先说…

108. 将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树 难度简单1214 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&…