相关文章:

架构风格和设计模式

设计模式

设计模式在 WIKI 上的定义:

The design patterns in this book are descriptions of communicating objects and classes that are customized to solve a general design problem in a particular context.

设计模式描述了一组类和对象之间的关系, 用以解决特定上下文内的某个常见的设计问题, 例如:

  • 观察者模式: 实现出版和订阅功能, 其定义了对象之间一对多的依赖关系, 一旦出版者发生改变, 所有依赖对象都会收到通知
  • 装饰者模式: 动态的将功能附加到对象上, 相比继承更加弹性, 解决类数量爆炸, 基类功能不适用于所有子类的问题
  • 工厂方法模式: 定义创建对象接口, 并将类的实例化推迟到子类中

风格和模式

什么是架构模式? 什么是架构风格? 架构模式和架构风格是什么关系?

架构模式在 WIKI 上的定义:

An architectural pattern is a general, reusable solution to a commonly occurring problem in software architecture within a given context

类似设计模式, 架构模式描述了一组组件之间的关系, 用以解决特定上下文某个常见的架构问题. 换言之, 架构模式是一个通用的, 可重用的解决方案, 用以解决特定上下文内的某个常见的架构问题. 简单描述: 架构模式是特定问题域下架构风格的具体应用.

架构模式在Roy Thomas Fielding博士Restful论文中有如下的定义:

An architectural style is a coordinated set of architectural constraints that restricts the roles/features of architectural elements and the allowed relationships among those elements within any architecture that conforms to that style.

一种架构风格是一组协作的架构约束,这些约束限制了架构元素的角色和功能,以及在任何一个遵循该风格的架构中允许存在的元素之间的关系。

从上面的两个定义可以了解到, 模式描述的是一种关系, 其有场景限制, 其用于解决特定的某类问题, 而架构风格则是一组组件的约束:

  • 架构模式: 针对某个特定上下文的某类问题的一个特殊的解决方案
  • 架构风格: 一种具有广泛意义的普适性解决方案或者约束

例如 CS(client-server)架构风格, 该架构风格有多种表现形式: 二层, 三层(MVC), N 层, 这些可以认为是架构模式.

术语

  1. 软件架构, 运行时抽象

一个软件架构是一个软件系统在其操作的某个阶段的运行时(run-time)元素的抽 象。一个系统可能由很多层抽象和很多个操作阶段组成,每个抽象和操作阶段都 有自己的软件架构。

软件架构的核心就是抽象原则

  • 层次方面: 一个复杂的系统包含多层抽象, 每一层抽象都会产生新的架构
  • 操作方面: 软件系统通常拥有多个操作阶段, 如启动, 初始化, 处理, 停止, 其中每一个操作阶段都是一个架构
  1. 元素

一个软件架构由一些架构元素(组件、连接器和数据)的配置来定义,这些元素之间的关系受到约束,以获得想要得到的一组架构属性。

架构元素分为处理, 数据, 连接元素, 而形式则基于 element 的属性以及属性之间的关系(约束)来定义, 进而通过选择架构风格, 结合元素和形式形成一个特定的架构.

  • 组件(处理): 一个组件是软件指令和内部状态的一个抽象单元,通过其接口提供对于数据的转换。
  • 连接器(连接元素): 一个连接器是对于组件之间的通讯、协调或者合作进行仲裁的一种抽象机制。
  • 数据: 一个数据是组件通过一个连接器接收或发送的信息元素。如字节序列、消息、 编码过的参数、以及序列化过的对象等.
  1. 配置

一个配置是在系统的运行期间组件、连接器和数据之间的架构关系的结构。

在配置的角度考虑, 组件是计算的所在地, 连接器是定义组件之间交互的机制, 配置则是相互交互的组件和连接器的集合, 一个配置等价于一组组件交互之上的特定约束.

  1. 属性

架构属性集合包括了对组件、连接器和数据的选择和排列所导致的所有属性. 属性是由架构中的一组约束所导致的. 架构设计的目标是创建一个包含一组架构属性的架构,这些架构属性形成了系统需求的 一个超集.

不同的约束产生不同的属性(品质, 特性), 反过来属性集合又为软件架构的质量或者品质提供了评价标准, 其中基于网络的应用的架构所关注的属性有如下几个:

  • Performance: 组件交互对于用户可觉察的性能 (user-perceived performance)和网络效率(network efficiency)来说是一个决定性因素.
  • Scalability: 可伸缩性表示在一个主动的配置中,架构支持大量的组件或大量的组件之间交互的能力。
  • Simplicity: 组件足够简单, 足够内聚, 足够低耦合, 一般使用分离关注点原则来作为考量依据.
  • Modifiability: 可修改性对于应用的架构所作的修改的容易程度, 是否可扩展, 是否可定制, 是否可配置, 是否可重用等等.
  • Visibility: 可见性是指一个组件对于其他两个组件之间 的交互进行监视或仲裁的能力, 如 WAF 防火墙的安全可见性, 分层机制提供的伸缩可见性等等.
  • Portability: 可移植性确保系统在不同环境下的正常运行.
  • Reliability: 可靠性表示对于故障的处理机制, 应对机制, 保障机制, 监视等.

关于属性的更加详细描述见第二章的详细说明.

  1. 风格

一种架构风格是一组协作的架构约束,这些约束限制了架构元素的角色和功能,以及在任何一个遵循该风格的架构中允许存在的元素之间的关系。

让我们重新回到架构的讨论, 回缩上面四个小点从而更好的理解架构风格, 架构是软件系统在运行时的抽象, 而软件架构的定义又是由三个元素组成(数据, 组件, 连接器), 对一组组件交互的特定约束产生了配置, 各种符合当前架构的约束不断的产生新的属性, 基于这些产生的属性我们不断整理收集再反馈过来评价架构本身的质量.

在 1.1 节我们阐述了架构模式, 设计模式, 架构风格的区别, 其中架构风格定义为一种广泛意义的普适性约束, 万变不离其宗, 所有的设计都是从实践中不断基类, 在大量积累的样本下我们对这些样本进行归纳总结并进而进行分类, 从而产生一种具有普适性的规则, 这就是架构风格产生的由来, 实际上这也是架构模式, 设计模式产生的由来.

风格是一种用来对架构进行分类和 定义它们的公共特征的机制, 每一种风格都为组件的交互提供了一种抽象, 且通过忽略架构中其余部分的偶然性细节来捕获一种交互模式的本质特征. 每一种架构风格决定了在此风格的实例中能 够使用的组件和连接器的词汇表,以及一组如何能够将它们组合在一起的约束.

属性

性能

  1. Network performance

网络性能这个度量手段用来描述通信的某些属性, 例如: 吞吐量, 负载, 带宽等.

  • 吞吐量表示信息在组件之间转移的速率
  • 负载包含初始配置负载和交互负载
  • 带宽是在一个特定的网络连接之上可用的最大的吞吐量.

不同的风格就会产生不同的网络性能, 不同组件之间交互的数据数量和粒度大小也决定了不同的网络性能, 例如 HTTP 协议相比 UDP 协议网络性能偏慢, websocket 协议在大数量, 小粒度的交互场景高于 HTTP 交互逻辑等.

  1. User-perceived Performance

用户可觉察的性能根据其对于使用一个应用的 用户的影响来度量, 即从使用者角度, 非真实的直观数据角度来表现一个应用真正的使用效率, 例如延迟, 完成时间等.

  • 延迟是指从触发初次请求到得到第一个响应指示之间持续的时间, 完成时间是完成一个应用动作所花费的时间.
  • 完成时间(completion)是完成一个应用动作所花费的时间.

其中延迟可能包括:

  • 应用识别出触发动作的事件所需的时间
  • 在组件之间建立交互所需的时间
  • 在组件间传输交互数据所需的时间
  • 组件处理每 个交互所需的时间
  • 在应用能够呈现一个可用的结果之前,完成数据的转移和处理 交互的结果所需的时间

对于延迟不同类型的优化可能对整体的完成时间产生副作用, 例如以压缩包为例, 对于跨越网络转移已编码的数据来说,这会导致 更短的完成时间, 但是如果这些压缩是在服务端即时(on-the-fly)进行的操作, 则会产生不可接受的延迟.

  1. Network Efficiency

通过尽可能的减少网络使用来提高网络效率, 尽可能使用应用的使用接近于内网的使用效果, 为了提高网络效率从而引入了多种机制:

  • 缓存: 重用先前的交互
  • 减少与用户动作相关的网络交互, 如连接的关闭(HTTP 长连接)
  • 地址: CDN, 移动代码等等

可伸缩性

为了改善一个系统的可伸缩性, 提高大量组件之间交互的能力

  • 简化组件, 尽可能职责单一
  • 服务分布到很多组件, 进行分散交互, 微服务架构就是基于部分该理念
  • 通过监视结果对交互和配置进行控制, 对分布式组件的管控, 互相之间的心跳监控等等

一个高伸缩性的系统就是能够简单的以更大规模来做以前可以做的事情, 其可以分为横向伸缩, 纵向伸缩:

  • 横向伸缩: 增加更多逻辑单元的资源并令它们像是一个单元一样工作, 大部分的分布式集群方案, 分布式文件系统, 负载均衡都是为了解决该问题.
  • 纵向伸缩: 在同一个逻辑单元内增加资源来提高处理能力, 例如提高 CPU, 提高内存, 增加磁盘等

简单性

使用分离关注点原则来处理组件的功能, 确保每一个组件都足够简单, 从而更加容易实现, 该原则也是模块化开发中的第一优先级原则, 确保每一个类足够简单, 功能足够单一, 足够高内聚, 低耦合. 另外, 使用通用性原则亦可以提高简单性, 例如对连接器使用通用性原则从而产生了中间件, 减少架构中的变数. 我们可以通过: 复杂性, 可理解性, 可验证性三个方面来量化一个系统的简单性.

从可理解性角度考虑, HTTP 的无状态使得服务器实现简单化, 不需要考虑上一次和下一次 HTTP 请求, 中间组件和连接器可以独立的理解每一个请求.

可修改性

对于一个 WEB 系统, 一般要求其可以动态的修改某些配置, 无需停止和 重新启动整个系统, 对于一个复杂的系统, 需要确保个别旧组件的升级不会影响其他组件的正常运行, 确保新旧组件能够共存并正常提供服务. 可修改性包含如下几个特性:

  • 可进化性: 一个组件实现能够被改变而不会对其他组件产生负面影响的程度
  • 可扩展性: 将一个新功能动态添加到已部署系统中并且不影响系统的其他部分, 组件之间的耦合度越低, 其可扩展性越高, 注意其非可伸缩性语境下的水平扩展, 垂直扩展
  • 可定制性: 指临时性的规定一个架构元素的行为的能力。如果一个组件的客户端能够扩展该组件的服务,而不会对其他客户端产生影响,则该组件就是可定制的。
  • 可重用性: 指一个应用软件中的组件、连接器和数据元素能够不做修改的在其他应用重用。
  • 可配置性: 服务部署之后通过配置来动态的接收新的数据, 新的组件

可见性

可见性指的是一个组件对于其他组件之间的交互进行监视或者进行中间周旋的能力。拥有了可见性之后,就可以通过共享缓存来改善性能、通过分层来改善可伸缩性、通过允许中间件(比如防火墙)对交互做出检查来改善安全性、通过监视来改善可靠性等。

可移植性

指软件在不同的环境下运行的能力。比如那些将代码和代码处理的数据放在一起移动的架构风格可以获得此架构属性,比如虚拟机风格、移动代理风格,以及那些限制只能使用标准格式的数据元素的架构风格。

可靠性

从应用软件的角度来看,可靠性是在组件、连接器和数据之间出现部分故障时,一个架构受影响的程度。通过避免单点故障、增加冗余、系统监视等方法来改善可靠性。一般而言, 可靠的评判角度有如下几点:

  • 应用程序表现出用户所期望的功能
  • 允许用户犯错, 允许用户以出乎意料的方式使用软件
  • 在预期的负载和数据量下性能满足要求
  • 系统能防止未经授权的访问和滥用

对于故障的处理, 对异常情况的容错能力, 这是评判一个系统健壮性的关键点.

基于网络的风格

风格和属性

在第一章我们简单的介绍了风格属性的定义, 在第二章分别较为详细的介绍了不同属性的定义和一些使用场景.从第一章我们可以知道架构风格是一组协作的架构约束, 当将架构风格应用于基于网络的 hypermedia 系统时就自然而然产生一系列第二章介绍的架构属性. 反过来, 我们可以根据各种架构风格产生的架构属性来判断每一种架构风格的优缺点以及相应的使用场景.

引用: