系统架构设计师教程(十)软件可靠性基础知识

2024-01-08 23:44:37

10.1 软件架构演化和定义的关系

10.1.1 演化的重要性

软件架构的演化是为了适应用户需求、业务环境和运行环境的变化,它涵盖了软件架构的全生命周期,包括需求获取、建模、文档、实现和维护等阶段。软件架构的演化的重要性体现在以下几个方面:

  1. 保障软件系统质量:软件架构支撑整个软件系统,决定其性能、可靠性、安全性和易维护性等关键属性。软件架构的演化可以确保软件系统满足用户需求,并具备市场竞争力和长期生命周期。

  2. 管控复杂性和变化性:软件架构作为蓝图提供了对整体复杂性和变化性的管控途径。基于软件架构进行检测和修改成本相对较低,能够更好地刻画软件演化,观察和控制演化中的影响效应。

  3. 保证一致性和正确性:软件架构的演化可以保证软件系统的一致性和正确性,并降低演化的成本。形式化、可视化表示提高了软件的可构造性,设计方案考虑未来可能出现的演化问题和环境,描述组件间的耦合有助于系统的动态调整。

总之,软件架构的演化是为了维持软件架构自身的有用性,并确保软件系统满足用户需求、具备良好的质量和功能属性,同时降低复杂性和变化性对软件演化带来的影响。

10.1.2 演化和定义的关系

软件架构演化的关键要素包括组件、连接件和约束。组件是软件架构的基本要素,表示系统中的计算元素、数据存储和重要模块。

组件的演化涉及模块的增加、删除或修改。连接件表示组件之间的交互关系,大多数情况下,组件的演化会导致连接件的演化,包括交互消息的增加、删除或改变。

约束是组件和连接件之间的拓扑关系和配置,它提供额外的数据支持,包括架构的约束数据和参数。

约束的演化体现在仿真数据的增加、删除或改变。组件、连接件和约束的演化可能会产生波及效应,并最终形成演化后的软件架构。

10.2 面向对象软件架构演化过程

10.2.1 对象演化

顺序图中组件的实体为对象,而对象包含了属性如接口、类型和语义等。对象属性的演化只影响对象自身,对描述对象之间交互过程的顺序图没有影响。在架构设计的动态行为方面,只有添加对象(AO)和删除对象(DO)会产生影响。AO表示在顺序图中添加一个新的对象,一般发生在系统需要实现新功能或提高架构灵活性的情况下。DO表示删除顺序图中的一个现有对象,一般发生在系统需要移除某功能或降低架构复杂度的情况下。对于发生演化的对象,如果它与其他对象没有交互关系,则可以认为对系统没有任何意义,因为这种演化不会影响架构的正确性或时态属性。因此,在对象演化发生时,通常会伴随相应的消息演化,新增相应的消息以完成交互,从而影响架构的正确性或时态属性。

10.2.2 消息演化

消息是顺序图的核心元素,包含了名称、源对象、目标对象、时序等信息。这些信息与其他对象或消息相关联,会直接影响对象之间的交互,从而对架构的正确性或时态属性产生影响。消息的演化可以分为增加消息、删除消息、交换消息顺序、反转消息、改变消息模块等五种类型。消息的演化会直接影响对象之间的交互行为,但不一定会违背约束。演化可分为与当前约束无关、与约束直接关联但不违背约束、与约束直接关联并违背约束三种类型。消息是顺序图的核心内容,消息演化是顺序图演化的核心,对象的演化伴随着消息演化。复合片段和约束也基于消息的存在,它们的演化受到消息演化的影响。在进行其他演化分析研究的同时,需要对相关的消息演化进行分析。

10.2.3 复合片段演化

复合片段是描述对象交互关系的控制流,与消息一起构成顺序图的内容。复合片段有不同的类型,包括会产生分支的和不会产生分支的。复合片段的演化可以分为增加、删除、改变类型和改变条件四种类型。增加复合片段会导致新的控制流分支,删除复合片段与增加复合片段相反,改变类型会改变交互流程,同时也可能涉及条件和内部执行序列的变化,改变条件会影响控制流的触发事件。复合片段的演化会对架构设计的正确性和时态属性产生影响,因此需要进行验证以确保演化后不会出现意外错误。

10.2.4 约束演化

顺序图中的约束信息以文字形式存储在对象或消息中,通常使用LTL来描述时态属性约束。约束演化对应着架构配置的演化,主要来源于系统属性的改变,而约束的改变往往伴随着消息的改变。约束演化的信息并未存储于定义的层次自动机中,因为约束缺乏可视化描述的方式,没有自动机描述方式。约束演化可以直接添加或删除约束信息。

  • AC(Add Constraint)直接添加新的约束信息,对架构设计产生直接影响,需要检查当前设计是否满足新添加的约束要求。
  • DC(Delete Constraint)直接移除某条约束信息,发生在去除不必要条件时,一般情况下,架构设计会满足约束的演化。 如果对约束信息进行修改,由于缺乏可视化描述,可以视为删除原有约束并添加新的约束,不再另行列出

10.3 软件架构演化方式的分类

目前,软件架构演化的分类方法有多种。以下是三种比较典型的分类方法:

  1. 基于实现方式和实施粒度分类:按照软件架构的实现方式和实施粒度进行分类,包括基于过程和函数的演化、面向对象的演化、基于组件的演化和基于架构的演化。

  2. 基于研究方法的分类:根据研究方法将软件架构演化方式分为四类。第一类是对演化的支持,例如代码模块化的准则、可维护性的指示(如内聚和耦合)、代码重构等。第二类是版本和工程的管理工具,例如CVS和COCOMO。第三类是架构变换的形式方法,包括系统结构和行为变换的模型,以及架构演化的重现风格等。第四类是架构演化的成本收益分析,用于决定如何增加系统的弹性。

  3. 静态演化和动态演化分类:按照软件架构的演化过程是否处于系统运行时期进行分类。静态演化发生在软件架构的设计、实现和维护过程中,软件系统还未运行或者处于运行停止状态。动态演化发生在软件系统运行过程中。

本章重点介绍软件架构的静态演化和动态演化。

10.3.1 软件架构演化时期

软件架构演化可以根据发生的时机和条件进行分类:

  1. 设计时演化:发生在体系结构模型和相关代码编译之前,修改时可以不考虑应用程序的状态,但需要考虑系统的体系结构。

  2. 运行前演化:发生在执行之前、编译之后,由于应用程序并未执行,修改时可以不考虑应用程序的状态,但需要考虑系统的体系结构,且系统需要具有添加和删除组件的机制。

  3. 有限制运行时演化:系统在设计时就规定了演化的具体条件,将系统置于“安全”模式下,演化只发生在某些特定约束满足时,可以进行一些规定好的演化操作。

  4. 运行时演化:系统的体系结构在运行时不能满足要求时发生的软件架构演化,包括添加组件、删除组件、升级替换组件、改变体系结构的拓扑结构等。此时的演化是最难实现的。

10.3.2 软件架构静态演化

软件架构演化可以根据发生的时机和条件进行分类。首先是设计时演化,即在体系结构模型和相关代码编译之前进行修改。其次是运行前演化,即在执行之前、编译之后进行修改。然后是有限制运行时演化,即系统在设计时就规定了演化的具体条件,只能在特定约束下进行操作。最后是运行时演化,即系统的体系结构在运行时无法满足要求时进行的演化,包括添加组件、删除组件、升级替换组件等操作。

静态演化过程可以看作经过一系列原子演化操作的组合。原子演化操作是指基于UML模型表示的软件架构中在逻辑语义上最小的架构修改操作。这些操作包括增加/删除模块间的依赖、增加/删除模块间的接口、增加/删除模块、拆分/聚合模块等。每个原子演化操作都会对架构产生影响,可能改变架构的组织结构和质量属性。不同的质量属性度量和评估会受到不同类型的原子演化操作的影响。

在与可维护性相关的架构演化操作中,模块间的依赖关系、接口和模块的增加/删除会影响架构的组织结构和外部质量属性。而在与可靠性相关的架构演化操作中,消息、交互对象、消息片段和用例执行的增加/删除/修改会影响交互场景的可靠程度。

正交软件架构是一种常用的静态演化处理方式。通过对功能进行分层和线索化,形成正交体系结构,使每个变动只影响一条线索,提高了演化的效率。其演化过程包括需求变动归类、架构演化计划制订、组件的修改/增加/删除以及更新组件之间的相互作用等步骤。最终形成演化后的软件架构作为系统更新的详细设计方案和实现基础。

10.3.3 软件架构动态演化

动态演化是指系统在运行期间进行的演化,需要在不停止系统功能的情况下完成,相比静态演化更加困难。动态演化的需求主要来自软件内部执行导致的体系结构改变和软件系统外部请求的重配置。对于长期运行且具有特殊使命的系统,动态演化能够减少更新费用和风险,并增强系统的自定义性和可扩展性。

动态演化包括软件动态性的等级和动态演化的内容。软件动态性分为交互动态性、结构动态性和架构动态性。根据修改的内容不同,软件的动态演化主要包括属性改名、行为变化、拓扑结构改变和架构风格变化。目前实现软件架构动态演化的技术主要有动态软件架构(DSA)和动态重配置(DR)。

动态软件架构(DSA)的实现基本原理是通过运行时刻的体系结构对象来触发系统自身的动态调整,需要提供相关的监控管理机制和保证演化操作原子性。DSA包括描述语言和演化工具的支持,例如π-ADL、Pilar、LIME等描述语言,以及反射机制、基于组件操作、π演算和外部体系结构演化管理器等演化工具。

动态软件架构的应用实例PKUAS是一个支持Java EE规范的组件运行支撑平台,采用微内核架构,包括容器系统、公共服务、工具和微内核等组件。PKUAS通过MBean接口对外提供管理相关的属性和操作,满足了动态演化的需求。

动态重配置主要指在软件部署之后对配置信息的修改,常见的模式包括主从模式、中央控制模式、客户端/服务器模式和分布式控制模式。动态重配置的难点包括约束定义困难、性能约束难以静态衡量、管理所有方面困难以及维持系统完整性和重配置策略正确和安全性的挑战。

10.4 软件架构演化原则

本节介绍了18种软件架构可持续演化原则以及相应的度量方案,主要包括演化成本控制、进度可控、风险可控、主体维持、系统总体结构优化、平滑演化、目标一致、模块独立演化、影响可控、复杂性可控、有利于重构、有利于重用、设计原则遵从性、适应新技术、环境适应性、标准依从性、质量向好和适应新需求原则。每个原则都有对应的解释和用途,以及度量方案来评估架构演化的效果。这些度量方案能够帮助评估架构演化的成本、进度、风险、结构、稳定性、独立性、影响、复杂性、重构性、重用性、设计原则遵从性、技术适应性、环境适应性、标准依从性、质量改进和新需求适应性等方面。

10.5 软件架构演化评估方法

10.5.1 演化过程已知的评估

  1. 评估流程:
  • 将架构度量应用到演化过程中
  • 对演化前后的不同版本的架构进行度量,得到度量结果的差值和变化趋势
  • 计算架构间质量属性距离,对相关质量属性进行评估
  1. 架构演化中间版本度量:
  • 对可维护性和可靠性进行度量,分析演化对外部质量属性的影响
  1. 架构质量属性距离:
  • 用来评估相邻版本架构间质量属性的差异
  • 分为可维护性距离计算方法和可靠性距离计算方法
  • 应针对同一架构的不同演化版本进行度量,以保障架构能够持续健康演化
  1. 架构演化评估:
  • 基于度量的方法帮助分析架构内部结构修改对外部质量属性的影响
  • 监控演化过程中架构质量的变化
  • 评估不同版本架构在质量属性上的差异,有利于架构维护及故障定位等。

10.5.2演化过程未知的评估

  • 当架构演化过程未知时,可以通过比较演化前后的度量结果来推测架构的变化。
  • 使用基于度量的方法对演化前后的架构进行评估,得到质量属性的差异并计算它们之间的距离。
  • 分析架构演化前后质量属性的变化和距离,推测可能发生的演化操作,并找出其影响因素。
  • 对每个演化操作分析其对质量属性的影响,并判断是否符合预期。
  • 若演化操作符合预期,则说明演化完成了任务;否则需要进一步演化来完善。
    在这里插入图片描述

10.6 大型网站系统架构演化实例

10.6.1 第一阶段:单体架构

大型网站是从小型网站发展而来,网站架构也是一样,是逐步演化而来。小型网站最开始只需要一台服务器就够了,应用程序、数据库、文件等所有资源都在一台服务器上,随着网站业务的发展,需要将应用和数据分离至不同的服务器,并进行进一步优化。
在这里插入图片描述

10.6.2 第二阶段:垂直架构

随着网站业务的发展,一台服务器无法满足需求,需要将应用和数据分离至不同的服务器。应用服务器需要更快更强大的处理器速度,数据库服务器需要更快的磁盘和更大的内存,文件服务器需要更大容量的硬盘。分离后,不同特性的服务器承担不同的服务角色,网站的并发处理能力和数据存储空间得到了改善。但随着用户逐渐增多,数据压力太大导致访问延迟,需要进一步优化网站架构。
在这里插入图片描述

10.6.3 第三阶段:使用缓存改善网站性能

网站访问的特点和现实世界的财富分配一样,遵循二八定律。为了减少数据库的访问压力,提高整个网站的数据访问速度,改善数据库的写入性能,可以将一小部分数据缓存在内存中,使用本地缓存和远程分布式缓存。本地缓存访问速度更快但受服务器内存限制;远程分布式缓存可以做到不受内存容量限制的缓存服务。然而,在网站访问高峰期,单一应用服务器能够处理的请求连接有限,成为整个网站的瓶颈。
在这里插入图片描述

10.6.4 第四阶段:使用服务集群改善网站并发处理能力

使用集群是网站解决高并发、海量数据问题的常用手段。当一台服务器无法满足网站持续增长的业务需求时,增加一台服务器分担原有服务器的访问及存储压力是更恰当的做法。这种方式可以持续增加服务器不断改善系统性能,实现系统的可伸缩性。应用服务器实现集群是网站可伸缩架构设计中较为简单成熟的一种。
在这里插入图片描述

10.6.5 第五阶段:数据库读写分离

通过使用缓存,网站可以减少对数据库的读操作,但仍有一部分读操作和全部写操作需要访问数据库。当网站用户规模变大时,数据库可能成为瓶颈。为了改善数据库负载压力,可以利用主从热备功能实现数据库读写分离。应用服务器在写数据时,访问主数据库,并通过主从复制机制将数据同步到从数据库。这样,在应用服务器读取数据时,可以直接从从数据库获取。为了方便应用程序访问读写分离后的数据库,通常会在应用服务器端使用专门的数据访问模块,使数据库读写分离对应用透明化。
在这里插入图片描述

10.6.6 第六阶段:使用反向代理和CDN加速网站响应

随着网站业务发展和不同地区的网络环境复杂,网站访问速度越来越慢,影响用户体验和流失率。为了提高网站访问速度,留住用户,可以使用CDN和反向代理两种方式。CDN部署在网络提供商机房,使用户可以从距离自己最近的机房获取数据;反向代理部署在网站中心机房,当用户请求到达中心机房后,首先访问的服务器是反向代理服务器,如果缓存中有用户请求的资源,就将其直接返回给用户。使用CDN和反向代理的目的都是加快用户访问速度并减轻服务器负载压力。
在这里插入图片描述

10.6.7 第七阶段:使用分布式文件系统和分布式数据库系统

对于大型网站持续增长的业务需求,单一服务器无法满足要求。通过数据库读写分离可以将一台服务器拆分为两台,但随着业务增长,需要使用分布式数据库和分布式文件系统。分布式数据库是最后的选择,通常在单表数据规模非常大时使用。网站更常用的数据库拆分方式是业务分库,将不同业务的数据部署在不同的物理服务器上。
在这里插入图片描述

10.6.8 第八阶段:使用NoSQL和搜索引擎

随着网站业务的复杂化,数据存储和检索需求也变得复杂。为了满足这些需求,网站需要采用NoSQL和搜索引擎等非关系型数据库技术。这些技术具有分布式特性和可伸缩性,能更好地支持网站的发展。通过一个统一的数据访问模块,应用服务器可以方便地访问各种数据源,减轻了应用程序管理多个数据源的负担。
在这里插入图片描述

10.6.9 第九阶段:业务拆分

为了应对复杂的业务场景,大型网站采用分而治之的策略,将整个网站业务划分为不同的产品线。例如,购物交易网站会将首页、商铺、订单、买家和卖家等功能划分为不同的产品线,并由不同的业务团队负责。
从技术上来说,根据产品线的划分,将网站拆分为多个独立部署的应用程序。这些应用程序可以通过超链接建立关联(例如首页上的导航链接指向不同的应用程序地址),也可以通过消息队列进行数据分发。此外,这些应用程序通常访问同一个数据存储系统,以构建一个关联的完整系统。

在这里插入图片描述

10.6.10 第十阶段:分布式服务

随着业务拆分越来越细致,存储系统变得庞大,整个应用系统的复杂度指数级增加,部署和维护变得更加困难。在大型网站中,由于每个应用都要与所有数据库系统进行连接,导致数据库连接资源不足,从而引发拒绝服务问题。

为了解决这个问题,可以将共享的业务操作单独提取出来,独立部署。这些可复用的业务通过连接数据库提供共享业务服务,而应用系统只需要管理用户界面,并通过分布式服务调用共享业务服务来完成具体的业务操作。

通过这种架构,大型网站可以解决大部分技术问题,包括跨数据中心的实时数据同步和与特定网站业务相关的问题,可以通过组合改进现有的技术架构来解决。
在这里插入图片描述

10.7 软件架构维护

软件架构是软件开发和维护过程中的重要组成部分,它连接了软件需求和设计、实现之间的关系。软件架构的开发和维护包括多个环节,如导出架构需求、架构开发、架构文档化、架构分析、架构实现和架构维护。

软件架构的维护与演化是紧密关联的,维护需要跟踪和控制软件架构的演化过程,以确保其能够满足需求。架构维护可以被看作是架构演化的一部分。

在软件架构维护过程中,通常涉及架构知识管理、架构修改管理和架构版本管理等内容。这些内容对于保障软件架构的质量和演化过程的可控性至关重要。

10.7.1 软件架构知识管理

软件架构知识管理旨在记录和评价架构设计决策,以帮助维护和演化架构。然而,目前存在一些问题,包括缺乏整理策略、文档化动机不足以及知识分享不充分。

架构知识的定义包括架构设计和架构设计决策,而架构知识管理的目标是捕捉架构知识并提供设计依据以进行记录和评价。

架构知识管理的需求在于提高架构知识的可获得性,并防止架构知识的丢失和流失。

然而,当前的实践存在问题,如缺乏实用的整理策略、文档化动机不足和知识分享不足。这些问题导致架构知识无法在组织中得到充分的分享和应用。

10.7.2 软件架构修改管理

在软件架构修改管理中,建立一个隔离区域 (RoQ) 是重要的做法。这保证了在 RoQ 中进行的修改不会对其他部分产生影响。为此,需要确定修改规则、类型和可能的影响范围和副作用等。

10.7.3 软件架构版本管理

软件架构版本管理为架构演化提供依据,可以控制、使用和评价架构的不同版本。例如,王映辉等人提出了一种基于组件-连接件模型的方法,通过邻接矩阵和可达矩阵分析和量化了静态演化中的波及效应,并计算了组件在架构中的贡献大小。他们还提出了动态语义网络模型,用于分析动态演化中的收敛情况,并给出了描述演化过程的邻接矩阵序列。这些方法为架构演化的分析提供了框架。

10.7.4 软件架构可维护性度量实践

首先,将组件图导出为XML文件,并解析出评估所需的数据。然后,根据可维护性的六个子度量指标,计算每个组件的度量结果。其中包括圈复杂度、扇入扇出度、模块间耦合度、模块的响应以及紧内聚度和松内聚度。最后,根据每个组件的度量结果计算出整个系统的度量结果。根据结果分析可知,圈复杂度、扇入扇出度、模块间耦合度、模块的响应等指标都与组件的关联关系和依赖关系有关。同时,高内聚度和低耦合度是设计良好的架构的目标。

文章来源:https://blog.csdn.net/u010095372/article/details/135466553
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。