什么是软件体系结构?
软件体系结构是具有一定形式的结构化元素,抽象的讲,软件体系结构包括构成系统的设计元素的描述,设计元素的交互,设计元素组合的模式,以及在这些模式中的约束。具体的讲,体系结构 = 组件+连接件+约束
组件:具有某种功能的可重用的软件模块单元,表示了系统中主要的计算单元和数据存储。
连接件:表示了组件之间的交互,简单的连接件有:管道,过程调用,事件广播等,复杂的连接件有:客户-服务器通信协议,数据库和应用之间SQL连接等。
约束:表示了组件和连接件的拓扑逻辑和约束。
七种经典的软件体系结构风格
能够回答以下四个问题:
- define (定义和特性)
- component & connectors (组件和连接件)
- usage examples (应用示例)
- advantages and disadvantages (优点和缺点)
pipe and filter(管道-过滤器)
组件和连接件
组件: filters -->处理数据流,一个过滤器封装了一个处理步骤。
连接件:pipes --> 连接一个源和一个目的过滤器。
定义和特性
每个过滤器都有一组输入集和输出集。过滤器从管道中读入数据流,对输入流进行内部转换和增量计算(丰富,精炼,转换,融合,分解),然后产生输出数据流并写入管道中。
特点:
- 每个过滤器必须是一个独立的实体:过滤器之间无需共享状态,即filter无需知道其输入管道和输出管道所连接的其他过滤器的存在,更不必关注相邻过滤器的实现细节。他仅仅需要对输入数据流进行特定的内部転换和增量计算,筛选出合适的数据。
- 数据到来是便被处理,不是收集然后处理,即在输入被完全消费之前,输出便产生了。
- **管道是将数据从一个过滤器的输出端移动到另一个过滤器的输入端,是一个单向流。**不同的管道中流动的数据流,可能具有不同的数据格式。
应用示例
编译器、Unix管道、图像处理,信号处理,声音与图像处理
优点和缺点
优点
- 良好的隐蔽性和高内聚、低耦合:可以将整个系统的输入输出行为看成多个过滤器功能的简单合成。
- 支持功能模块的重用:任意两个过滤器只要相互间所传输的数据格式上达成一致,就可以连接在一起
- 系统容易维护和拓展:新的过滤器容易加入到系统中,旧的过滤器也可被改进的过滤器替换
- 允许对一些如吞吐量,死锁 等属性进行分析
- 支持并行执行:每一个过滤器既可以独立运行,也可与其他过滤器并发执行。
缺点:
- 不适合处理交互的应用
- 系统性能不高,并增加了编写过滤器的复杂性:数据传输缺乏通用标准,每个过滤器绝大部分时间消耗在数据格式的解析,转换,合成上。同样也不适用于大量共享数据的应用设置。
调用-返回风格
主程序/子程序风格
组件和连接件
组件:过程和明确可见的数据
连接件:过程调用和显式的共享数据
控制结构:单线程
特点
调用和定义层次结构,子系统通常通过模块化来定义。
系统通常会被组织成一个主程序和一系列子程序的集合。主程序担当子程序的驱动器,为子程序提供一个人控制环路,使子程序以某种次序顺序执行。
ADT & OO
组件和连接件
组件:对象(抽象数据类型的实例)
连接件:过程调用
特点
在基于面向对象的模式中,操作和数据绑定在一起,隐藏实现和其他秘密。对象通过过程调用来实现交互。有两个重要方面:
- 对象维护自身表示的完整性
- 这种表示对其他对象是隐藏的
优点和缺点
优点:
- 面向对象易维护,易复用
- 对象反映现实世界,容易分解一个系统
- 对象对客户实现了隐藏细节,所有可以在不影响其客户的情况下改变对象的实现 。
缺点:
- 对象的管理比较复杂,当一个对象和其他对象交互,必须知道其他对象的标识。每当一个对象的标识改变的时候,必须修改那些显示调用它的对象。
分层系统
组件和连接件
组件: 在某些层中实现虚拟机
连接件: 协议, 规定了层次之间的交互方式
拓扑结构: 限制相邻层之间的交互
特点
- 一个分成系统是按照层次结构组织的,每一层向它的上层提供服务,同时它又是下层的客户。
- 上层必须知道下层的身份,不能调整层次之间的顺序。
- 大的问题分解成若干渐进的小问题,逐步解决,隐藏了很多复杂度。
- 内层只对其相邻的层和某些用于输出的函数是可见的,对其他外部的层是隐藏的。
- 修改一层,最多影响两层, 通常只会影响上层。若层之间接口稳固,则不会造成其他影响
- 层层相调,影响性能。
优点和缺点
优点:
- 支持基于逐级抽象的系统设计,这允许设计者将一个复杂的问题分解成一系列递增的步骤。
- 支持扩展,由于分层系统每一层最多和上下两层交互,对于任意一层功能的交互最多只影响其他两层。
- 支持重用,如果能保证为相邻的层提供一致的接口,他允许系统中同一层的不同实现相互交换使用。(即给同一接口建立不同实现)
缺点
- 定义一个合适的抽象层次可能会非常困难。比如,实际的通信协议体就很难映射到ISO框架中,因为其中许多协议跨多个层。
客户端/服务器风格
两层C/S架构
特点
服务器(后台)负责数据管理,客户机(前台)完成与用户的交互任务。“胖客户机,瘦服务器”
缺点
– 对客户端软硬件配置要求较高,客户端臃肿
– 客户端程序设计复杂
– 数据安全性不好。客户端程序可以直接访问数据库服务器。
– 信息内容和形式单一
– 用户界面风格不一,使用繁杂,不利用推广使用
– 软件维护与升级困难。每个客户机上的软件都需要维护
三层C/S架构
与二层C/S结构相比,增加了一个应用服务器。
应用功能分为表示层、功能层、数据层三层。
– 表示层是应用的用户接口部分。通常使用图形用户界面
– 功能层是应用的主体,实现具体的业务处理逻辑
– 数据层是数据库管理系统。
– 以上三层逻辑上独立。
整个应用逻辑驻留在应用服务器上,只有表示层存在于客户机上:“瘦客户机”
浏览器/服务器风格
B/S架构
B/S体系结构是三层C/S体系结构的特例,客户端有http浏览器即可
• 只能“拉”,不能“推”
• 客户之间的通信只能通过服务器中转
• 对客户机资源和其他网络资源的利用受限
• B/S结构的安全性较难控制(SQL注入攻击…)
• B/S结构的应用系统在数据查询等相应速度上,要远远低于C/S体系结构
• 服务器的负荷大,客户机的资源浪费
数据为中心的体系结构风格
定义
Data-centered style architectures involve a shared
data source approach to information passing.以数据为中心的风格架构涉及到信息传递的共享数据源方法。
典例: 注册表 剪切板
仓库体系结构风格
仓库是存储和维护数据的中心场所。
组件: 中心数据结构,表示当前数据的状态
连接件:仓库与独立构件之间的交互
应用场合:数据库、仓库形式的编译器结构、仓库形式的编译器结构
黑板体系结构风格
事件系统体系结构风格
主要特点
✓ 事件的触发者并不知道哪些构件会被这些事件影响,相互保持独立。
✓ 不能假定构件的处理顺序,甚至不知道哪些过程会被调用。
✓ 各个构件之间彼此之间无连接关系,各自独立存在,通过对事件的发布和注册实现关联。
A component(Event Source) can annonce (or broadcast) one or more events. 一个组件可以广播一些事件。
Other components(Event Handlers) in the system can register an interest in an event by associating a procedure with it. 系统中的其它构件可以注册自己感兴趣的事件,并将自己的某个过程与相应的事件进行关联。
When the event is announced the system (Event Manager) itself invokes all of the procedures that have been registered for the event. 当一个事件被发布,系统自动调用在该事件中注册的所有过程。
应用示例
调试器中的断点处理
Event Source:debugger (调试器)
Event Handler:editor and variable monitor (编辑器与变量监视器)
Event Manager:IDE (集成开发环境)
✓ 编辑器与变量监视器向调试器注册,接收“断点事件”;
✓ 遇到断点,调试器发布事件,从而触发“编辑器”与“变量监测器”
✓ 编辑器将源代码滚动到断点处;
✓ 变量监测器则更新当前变量值并显示出来。
美团平台
事件系统派遣机制
无独立调度模块的事件系统
This module is usually called Observable/Observer (被观察者/观察者).
Each module allows other modules to declare interest in events that they are sending. (每一个模块都允许其他模块向自己所能发送的某些消息表明兴趣)
Whenever a module sends an event, it sends that event toexactly those modules that registered interest in that event.
(当某一模块发出某一事件时,它自动将这些事件发布给那些曾经向自己注册过此事件的模块)
有独立事件派遣模块的事件系统
事件派遣模块是负责接收到来的事件并派遣它们到其它模块。
全广播式(All broadcasting) :派遣模块将事件广播到所有的模块,但只有感兴趣的模块才去取出事件并触发自身的行为;
选择广播式(Selected broadcasting) :派遣模块将事件送到那些已经注册的模块中。
选择广播式的两种策略:基于事件被执行的方式
Point-to-Point (message queue)(点对点模式:基于消息队列)
Publish-Subscribe(发布-订阅模式)
软件体系结构描述
文档建立的原则
◆ 1.从读者的角度写。
◆ 2.避免不必要的重复。
◆ 3.避免歧义。
◆ 4.使用标准组织结构。
◆ 5.记录理由。
◆ 6.保持文档时效性但不是频繁更新(有限的稳定性)。
◆ 7.审查文档是否符合需求
软件体系结构建模
“4+1”视图模型从5个不同的视角包括逻辑视图、进程视图、物理视图、开发视图和场景视图
来描述软件体系结构。每一个视图只关心系统的一个侧面,只有5个视图结合在一起才能反映系统的软件体系结构的全部内容。
用例视图 (场景)
◼ 从外部世界的角度描述正在建模的系统的功能。
◼ 需要使用此视图来描述系统应该执行的操作。 所有
其他视图都依靠用例视图(场景)来指导它们,这
就是将模型称为4 + 1的原因。
◼ 该视图通常包含用例图,描述和概述图。
用例图
理解系统功能需求,系统提供的功能的描述。
用于显示若干角色以及这些角色与系统提供的用例之间的连接关系。
重要的是记住用例代表了系统的外部视图。因此,不要期望用例与系统内部的类之间存在任何关联。
逻辑视图
◼ 描述系统各部分的抽象描述。用于建模系统的组成部分以及各组成部分之间的交互方式。
◼ 通常包括类图,对象图,状态图和协作图。
类图
类图表示系统中的类和类与类之间的关系,它是对系统静态结构的描述。
对象图
对象图是某个时间点系统中对象的快照,因为它显示的是实例而不是类,所以通常称为实例图。
状态图
状态图是描述类的对象所有可能的状态以及事件发生时状态的转移条件。
协作图
协作图是一种交互图,强调的是发送和接收消息的对象之间的组织结构。一个协作图显示了一系列的对象及对象之间的联系以及对象间发送和接收的消息。
过程视图
◼ 描述系统中的进程。 当 可视化系统中一定会发生的事情时,此视图特别有用。
◼ 该视图通常包含活动图。
活动图
描述满足用例要求所要进行的活动以及活动间的约束关系,有利于识别并行活动
开发视图
◼ 描述系统的各部分如何被组织为模块和组件。管理系统体系结构中的层非常有用。
◼ 该视图通常包含包图和组件图。
包图
包是在UML中用类似于文件夹的符号表示的模型元素的组合,允许从UML中获取任何结构,并将其元素分组到更高级别的单元中。
组件图
组件图描述代码构件的物理结构及各构件之间的依赖关系。将系统划分为组件并希望通过接口或组件细分为较低级别的结构来显示其相互关系
物理视图
◼ 描述如何将前三个视图中所述的系统设计实现为一组现实世界的实体。该视图中的图表展示了抽象部分如何映射到最终部署的系统中。
◼ 该视图通常包含部署图。
部署图
部署图定义系统中软硬件的物理体系结构。描述了一个运行时的硬件结点,以及在这些结点上运行的软件组件的静态视图。 显示了系统的硬件,安装在硬件上的软件,以及用于连接异构的机器之间的中间件。
质量属性场景
六个组成部分
➢ 刺激源(source):谁造成的刺激
➢ 刺激(stimulus):一个影响系统的情况
➢ 制品(artifact):系统被影响的部分
➢ 环境(environment):刺激发生时系统所处的状态
➢ 响应(response):刺激所产生的结果
➢ 响应衡量指标(response measure):如何评估响应
生活案例![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/94f758e8121d5d0b06beedc28757f19e.png#pic_center)
可用性
关注点
✓ 是否发生了故障(无法提供正常的服务,被外界发现)
✓ 故障的后果
衡量指标
✓ 可用(或故障)时间百分比
✓ 修复故障所需的时间
✓ 平均无故障时间
➢刺激源
✓ 故障的迹象(来自内部或外部)
➢刺激
✓ 系统出错
✓ 系统崩溃(反复出错)
✓ 给出结果不准时(早或晚)
✓ 给出错误结果
➢制品
✓ 计算 or 存储 or 网络传输
➢环境
✓ 正常状态 or “亚健康”状态
➢响应
✓ 记录日志(错误报告),回传给厂家
✓ 通知管理员或其他系统
✓ 关闭系统,系统在维修期间不可用
➢响应衡量指标
✓ 故障时间百分比、修复故障所需时间、平均无故障时间……
提升可用性的策略
➢ 方向1:故障检测
- Ping/echo
监控组件不定期向被监控组件发出ping消息,并根据收到的echo消息(是否收到、延时)做出响应
- Heartbeat(心跳)
被监控组件定期向监控组件发出心跳消息
在节点间保持周期性的心跳信号以检测各个节点的状态。若连续未收到的心跳信号到了一定的数目,就认为相应的系统已经出现故障。
- Exceptions(异常)
抛出 + 捕获 + 处理
需要编程语言支持
➢ 方向2:故障恢复
-
投票
- 多个冗余的组件,用统一或不同的算法来完成同一个任务。如果计算结
果不同,则少数服从多数
- 为降低同时出错的概率,多个组件可以由不同的开发团队在不同的软、
硬件平台上开发
-
主动冗余
- A、B服务器完成同样的运算(A和B的状态时刻保持一致),平时只取
A算出的结果
- 当A出现故障时,系统可以极快地切换到B
-
被动冗余
- A服务器完成运算后的一定时间内把自身状态告知B,B再把自身状态更
新为A的状态。
- 当A出现故障时,首先需要确认B的状态是最新的.
-
内测
开发人员修正bug,并在内部进行测试,确认无误后再发布补丁
-
检查点/回滚
定期保存,便于恢复
➢ 方向3:故障避免
- 服务下线
- 惹不起,躲得起
- 如果明确知道即将遭到毁灭性攻击,不如主动下线
- 事务
- 多个操作必须全部完成(银行转账)
- 进程监控
- Windows任务管理器
可修改性
关注点
✓修改的成本
✓系统的哪些部分被修改
✓修改发生的时间
✓修改由谁来进行
提升可修改性策略
目标:降低修改的时间和成本
限制修改范围:让修改所影响的软件范围尽可能的小
模块高内聚、低耦合:尽量把对程序的修改控制在一个模块内,可以借助框架、中间件
考虑到可能会发生的修改
➢有助于评估模块间责任的划分
➢ 让一个点的修改只影响一个模块
➢ 避免完全无关的多个修改会影响同一个模块
让模块通用:“解释器”风格的思路
隐藏信息:面向对象机制中的可访问性(public/private)
维持接口不变:在接口不变的情况下,接口连接的双方可以独立变化
限制通信路径:设计模式中的Façade模式
使用中介
➢ 数据中介:共享数据的风格
➢ 服务中介:设计模式中的bridge、factory method等模式
命名服务器(name server):查询所需资源 / 对象的位置,解决位置依赖
按需创建实例:借助设计模式中的创建型模式
延迟绑定时间:让软件在运行期间仍可进行灵活修改
配置文件:修改配置文件,而不用修改代码
发布-订阅模式
➢ 软件体系风格部分已有介绍(事件系统)
➢ 设计模式中的“观察者模式”
- 多态:用不同的子类,实现不同的功能
性能
关注点
✓ 系统响应事件的速度
✓ 和事件的数量和到达模式有关
响应衡量指标
✓ 处理事件所花的时间
✓ 单位时间内处理事件的数目
✓ 处理的错误率/丢失率
提升性能的策略
方向1:资源的需求
- 在要处理的数据量不变的情况下,提高计算效率
➢ 使用更高效率的算法
➢ 减少处理事件时对资源的占用
- 减少要处理的数据总量
➢ 控制事件到来的速率
➢ 只抽取一部分请求来处理
- 限制执行时间
➢ 在规定时间内得到近似解
- 限制待处理事件队列长度
➢ 直接放弃处理一部分事件
方向2:资源的管理
利用并发机制:多线程、多进程、多核、多机……
增加可用资源: 计算资源、存储资源、带宽资源……
方向3:资源的仲裁
➢ 先来先服务
➢ 固定优先级调度➢ 动态优先级
安全性
关注点
✓ 在保证合法用户使用系统的前提下,抵抗对系统的攻击
提升安全性的策略
方向1:抵抗攻击
- 用户的证实:密码、验证码、生物识别……
- 用户的授权: 确认用户的操作是在其权限范围
- 维持数据的保密性:给数据和传输过程加密
- 维持数据的完整性:MD5码校验
- 减少暴露:关闭无用端口、自启动的服务、无线路由SSID等
- 限制访问:白名单、黑名单
方向2:检测攻击
软件和人结合:入侵检测系统、安全专家
方向3:从攻击中恢复
恢复状态:使用“可用性”中的相关策略
攻击者的识别:也能震慑潜在的攻击者
可测试性
关注点
✓ 让软件的bug容易被测试出来
✓ 验证软件产品与它的需求规格是否匹配(存在不符或缺失)
✓ 使用最小的成本和工作量来验证软件的质量
提升可测试性的策略
黑盒测试
记录 / 回放: 自动化/半自动化测试
把接口和实现分离开:不同的排序算法,使用相同的接口提供专用的测试路径
白盒测试
内部监控:IDE提供的断点等调试工具、WinDbg等工具
Appium(APP UI测试)
Selenium(Web UI测试)
JMeter(接口测试、性能测试)
易用性
关注点
✓ 让用户使用软件的难度降低
提升易用性的策略
方向1:运行时策略
- 系统猜测用户要完成的任务:输入法联想、搜索引擎联想
- 系统给用户适当的反馈:提示拷贝文件所需的剩余时间、浏览器打开页面的进度
- 系统给用户提供一致的体验:鼠标提供DPI调整,适应不同的分辨率
- 支持撤销操作:减少误操作的影响
方向2:设计时策略
把用户界面和系统其它部分隔离开:MVC模式,支持用户界面的独立修改(甚至用户可以自行修改用户界面)
体系结构评估ATAM(Architecture Trade-off Analysis Method )
utility tree
效用是树的根结点,代表系统的整体质量。质量属性构成树的二级节点。在每个质量属性下对该质量属性做了进一步的说明。所设置的优先级是用高(H)、中(M)、低(L)的形式。
(M,L)优先级解释
- 第一个字母代表:每个场景对系统成功的重要影响程度
- 第二个字母代表:体系结构设计师所估计的实现这种场景的难度
risks, non-risks, sensitivity points, and tradeoffs
sensitivity points
A sensitivity point is a property of one or more components (and/or component relationships) that is critical for achieving a particular quality attribute response.
“The level of confidentiality in a virtual private network might be sensitive to the number of bits of encryption. ”敏感点是一个或多个组件(和/或组件关系)的属性,对于实现特定的质量属性响应至关重要。
e.g. 虚拟专用网络的保密级别可能对加密的位数很敏感。
tradeoff
A tradeoff point is a property that affects more than one attribute and is a sensitivity point for more than one attribute.
“Changing the level of encryption could have a significant impact on both security and performance.”权衡点是影响多个属性和的属性,是多个属性的敏感点。
e.g.“改变加密级别可能会对安全性和性能产生重大影响。
risks
A risk is a potentially problematic architectural decision.
“The level of confidentiality in a virtual private network might be sensitive to the number of bits of encryption. ”风险是一个潜在的有问题的架构决策。
e.g.“虚拟专用网络的机密程度可能对加密的比特数很敏感。”
non-risks
Non-risks are good architectural decisions that are deemed safe upon
analysis.
“Assuming message arrival rates of once per second, a processing
time of less than 30 ms, and the existence of one higher priority
process, a 1 second soft deadline seems reasonable.”无风险是被认为是安全的良好架构决策分析。
e.g.假定消息的到达速率是每秒一次,一次处理的时间小于30ms。如果对一个更高优先级的处理的响应时间要求是1秒钟,此系统可行
期末考试
客观题(30分)
两道简答题(5*2 = 10)
- 什么是软件体系结构?
- 描述“虚拟机风格”体系结构,并举出一个典型例子
十道选择题(2*10 = 20)
-
六种质量属性的提升策略
-
看图片中所给的是哪种体系结构风格
-
UML各种图的功能和结构
三道大题(70分)
- 场景题:
- 涉及到什么质量属性
- 画出每一种质量属性的场景(六要素:刺激源,刺激,制品,环境,响应,响应衡量指标)
- 针对每种质量属性,至少写出两种提升策略
- 该系统最适合用什么体系结构风格,说明原因,并阐述该种体系风格的优点和缺点
- 画效应树
- 写风险点,非风险点,敏感点,权衡点的概念,并将下面的陈述句归类到这四种里。
刚考完试,发波笔记攒人品,过过过! 2020/8/18
参考
《软件体系结构》 Mary Shaw David garlan著
课件