当前课程知识点:面向对象分析与设计 >  描述运行态软件体系架构 >  描述运行态软件体系架构 >  描述运行态软件体系架构

返回《面向对象分析与设计》慕课在线视频课程列表

描述运行态软件体系架构在线视频

描述运行态软件体系架构

下一节:描述分布式系统架构概述

返回《面向对象分析与设计》慕课在线视频列表

描述运行态软件体系架构课程教案、知识点、字幕

同学们,今天呢我们讲《面向对象分析与设计》的第18课:描述运行态软件体系架构

在这一节里面,我们首先讲描述运行体系架构活动的目的是什么,以及在IVP的软件开发过程中哪个阶段来执行它

在运行态体系架构中,主要的组成元素就是进程和线程,我们如何来建模进程和线程

在UML里面,没有缺乏对这个进程的建模方法

我们要讲如何采用类、对象、组件来描述进程和线程

以及描述线程和进程之间的关系

在设计阶段,我们需要对分析阶段我们所定义的初始的体系架构作进一步的精化

在精化软件体系架构的时候,我们需要描述它的运行态体系架构

比如说,对运行态体系架构的描述,是在这个体系结构精化阶段,由架构师负责完成

运行态体系架构的描述分析活动呢,他主要是考虑在初始体系架构的基础之上

针对性能、可靠性、可伸缩性这样一些非功能性需求,进行运行态体系架构的设计

所以 描述这些非功能性需求的附加规格说明书 是他的主要输入

除此以外 我们在初始体系架构设计里面

我们所定义的这个初始的体系架构 包括他描述体系架构实现的设计模型 也是他的一个输入

他的输出则是对体系架构一个更新 或者说一个细化 以及对我们在初始体系架构里面定义的设计模型的一个细化

所以,他的输出同样也是软件体系架构文档和设计模型

在UML里面,我们采用4+1视图来描述软件的体系架构

对于运行态体系架构 我们就采用的是进程视图来描述

也就是说 我们通过进程视图 我们就可以描述运行态的软件体系架构

为什么我们要引入运行态体系架构呢

这主要是因为 在现代软件里面 有很多任务是需要并发处理的

也就是说很多任务 很多软件的控制流是多个

在这种情况下 我们就需要做并发计算

也就是说需要描述它的运行态体系架构

这里我们给了个例子

最上边呢 是一个并行的 它需要两个车道

但是这两个车呢 只能跑在自己的车道里面

那么这种情况下 每个车独立的跑在自己的车道上

他们相互不需要 或者说几乎不需要任何同步

那么第二个图呢 我们也是两个车道

但是这两个车呢 有可能会变道超车

那么在这种情况下 这两个车之间可能就需要有一些同步 或者说协调

最复杂的情况呢 是下面这种 我们看它是过十字路口

为了防止在十字路口出现交通事故或阻塞

我们需要很好的协调不同车道或者说不同方向过来的汽车

比如说我们需要非常好的一种同步协调机制

在软件里面 我们把每个进程或者每个任务 独立运行的任务 也可以看成一个车

所以软件里边 在并行运行态体系架构里边

这些多个并行运行的进程或者任务 也必须要考虑它们之间的同步和协调问题

在软件里面引入并发 或者说引入并行 有什么样的帮助呢

或者为什么要引入呢 主要有这么一些需求

首先呢 我们知道有些软件 特别是像工业控制软件

它是根据外部传感器所采集到的事件或者信号来进行处理

那么对于这些随机产生的事件或者信号

我们需要有独立的处理流程 或者处理进程、线程去响应它

第二种情况下呢 我们知道现在的计算机硬件已经进入到了多核、多处理器时代

在多核、多处理器时代 为了让每一个处理器能够最大的发挥它的资源利用率

这样的话呢 我们就需要设计多进程或者并发程序

让每一个CPU都能够有一个进程或者任务去运行 以提高整个系统的利用率

最后呢 还有一些系统 当大的并发用户同时访问的时候

为了提高整个系统的响应时间 响应效率 能够支撑更多的用户的并发访问

我们也需要把整个系统设计成多进程或者多线程这样一些并发程序

那么为了实现这个多进程、多线程的并发访问 我们需要一些支撑机制

那么主要的支撑机制有这么几个

第一种情况下 就是在硬件层面上我们就提供有多处理器

也就是说多CPU 这样的话呢每个CPU可以独立的运行一个进程或者一个任务

那么第二种情况下 即使在单处理器的情况下

我们可以通过操作系统对于CPU的模拟或者虚拟仿真

使得通过操作系统的分时分区这样一些机制

可以在单个CPU的基础上虚拟出很多 或者说非常多的虚拟的处理器

使得每个任务可以得到一个独立的一个虚拟处理器 可以并发运行

那么最后一种情况下 即使硬件不支持 操作系统不支持

我们也可以让应用程序自身来同时管理多个任务 可以让应用程序来自己控制自己

在合适的时间 来执行不同的任务分支

在多任务比较普遍的情况下 运行态体系架构是软件体系架构描述的非常重要的一个方面

为了描述运行态体系架构 我们的步骤主要有这么几个

首先第一步 分析并发需求

第二步 识别系统需要定义的进程或者线程

第三个 对每个进程、线程定义它的生命周期

第四步 把我们前面所识别出来的设计元素 类、子系统等分配给这些进程或者线程

最后 我们要通过描述这种建模元素 给进程之间分配关系

下面呢 我们来首先看第一个 分析并发需求

那么在软件系统设计过程中 为什么要做并发呢 主要有这么几个原因

第一个原因 很多现代系统都是分布式系统

在分布式系统上 整个系统中会有多个不在同一个结点的多个处理器或者多个计算节点

我们需要保证 每个计算结点上都有一个相对独立的一个运行程序

所以我们就必须要设立多个任务 或者多个进程 或者多个线程

第二种情况下呢 很多系统是事件驱动的 最典型的就是我们工业控制系统

我们会根据传感器从现场采集到的数据 来计算、生成控制策略 来控制现场设备

那么对于这样一些系统来讲 当它随机地接受到外部的事件或者请求的时候 需要对每一个事件和请求进行响应

也就是说 在接收到事件以后需要创建一个独立的线程去执行和触发它

那么还有一些情况下 我们有一些系统他有复杂的算法 它的算法非常复杂耗时

为了提高计算的效率 我们可能把这个算法作并行计算处理

以使得这个算法的处理时间能够降低 或者提高算法的处理效率

最后 还要考虑整个软件硬件环境的并发处理能力

上面这些需求都可能驱使我们采用多并发的设计 这样的话我们就需要描述它的运行的体系架构

当然这种并发需求也可能会有冲突 我们可以根据它的重要性对它进行排序 来解决冲突问题

这是我们举的例子 在我们做的课程注册管理系统里边 我们可以看到的并发需求主要的有这么些

第一个 我们的课程系统可能会有多个学生或者老师并发访问

为了保证每一个学生和老师的访问都能得到及时响应 我们可能需要设计成并发程序

第二种情况下呢 一个开设的课程在学生选课的时候如果已经选满了

那么后面 再新选的同学我们需要给他发一个通知 比如说发一个邮件

那么这样的话 发邮件的这个程序可能就需要有独立的任务、独立的进程或者线程来处理它

第三点 可能进行基于风险的原型分析后我们发现

我们在开设课程里边我们需要从遗留的课程目录数据库里边查找课程信息

但过去的遗留系统它的性能没有办法满足我们当前软件的性能要求

所以我们需要采用多进程的方式来处理它

下面 我们讲如何来识别进程和线程

我们首先回忆一下 什么是进程 什么是线程呢

我们在操作系统课里面我们讲过 进程是什么呢 是软件运行的一个独立的控制流

而且每个进程是独立的 这是指它独立的分配CPU资源 独立的占有文件内存等其他的系统资源

进程比较重 创建撤销包括进程间通信都需要消耗大量的资源

在这种情况下 我们又提出一种轻量级进程 也就是我们这里后面讲到的线程

线程 它也能够独立执行 但是它不能独立的占有资源

所以 所有的线程它是共享它所包含的进程的资源

也就是说 线程运行的上下文和它所处的进程是一样的

这样的话呢 对于线程的创建、撤销包括线程间的通信都只需要消耗很少的或者说甚至不需要消耗系统资源

在系统里面 我们对于每一个独立的控制流我们需要创建一个进程或者线程

那么怎么来分别或者区分什么情况下是需要有一个独立的控制流的呢

可以从以下几个方面

第一个 就是从多处理器或者多计算节点

我们知道在每个CPU上 它要运行至少它要有一个独立的任务

这个任务可能是一个进程或者线程 也就是说 我们在我们系统里面有多少个进程或者线程

我们至少需要给它匹配对应的进程或者线程

这样才能使得每个CPU至少能够分配到一个进程或者线程来运行

第二种情况下 我们可能需要提高CPU的利用率

我们知道进程在运行的过程中 它可能会因为IO等原因进行阻塞

如果是CPU上有多个进程 那么当前进程阻塞之后其它的进程又可以继续运行

这样呢 不会让CPU在等待被阻塞的进程而空闲

所以多进程多任务的情况下可以提高CPU的利用率

第三种 服务时间触发的事件

在软件设计里边 有一些任务是周期性的或者定时任务

比如说 我们的很多系统 每天晚上凌晨1点要进行系统维护

那么系统维护这个任务 它就是固定时间来执行的

所以针对这种时间相关的这样一些任务或者说这样一些事件的处理

我们需要给它识别、定义独立的进程或者线程

第四种情况下 则是考虑有一些任务或者活动是有不同优先级的

为了使得高优先级的任务能够及时响应

我们需要把它和低优先级的任务分别定义在不同的进程或者线程里边

这样当高优先级的任务需要执行的时候

因为它的进程或者线程优先级高 它就会立即被CPU所调度 立即得到运行

再下来一种情况下 就要考虑可伸缩性

我们知道很多系统 它的业务 就是用户并发访问的需求 它是变化的

典型的例子 像淘宝 每年到了双11的时候它的用户量会暴增

平时的话 它的业务量肯定没有那么多

那么对于这种系统 就是说对于这种用户的并发访问数有可能会突然增加的情况下

我们的系统就必须具有良好的可伸缩性

那么采用多进程多线程的时候 我们就可以在用户访问量增加的时候

可以给它创建更多的进程、创建更多的线程 再给他增加相应的硬件资源

来满足整个系统的可伸缩性需求

还有一些情况下 软件系统运行过程中 软件的某些部分或者某些任务

它有更高的安全要求

对于这些有更高的安全性要求的这样一些软件的程序部分

我们也可以考虑把它单独实现成一个进程或者线程

以使得对它的安全防护可以独立进行 或者说可以提高它的安全防护等级

再下来 我们有时候还出于考虑系统的可用性

系统可用性是指用户在请求能够得到及时正确响应的概率

我们知道软件里面不可避免的存在缺陷或者存在Bug

那如果我给它找一个备份 本来我们只有一个进程

那我现在让它除了主进程以外 再给它创建一个备份进程

那么有两个进程同时运行 那么两个进程同时出错的概率就会比单个进程运行出错的概率要低很多

最后 就是支持一些主要的子系统

有一些子系统 可能是我们想复用已有的

那我们就可以把这些独立的子系统设计成一个独立的的进程或者线程

以更好的去复用它

在UML里面 是没有定义标准元素去建模进程的

这样就要求我们必须对UML的基本元素进行扩展

来定义描述进程或者线程的元素

在UML里边 我们通常情况下选择把类或者组件进行扩展

这里我们以类为例

我们把类这个对象扩展以后可以采用构造型分别来定义它的进程或者线程

然后采用类之间的依赖关系来描述进程和线程之间的这样一种关系

这是我们课程教学管理系统里面的一个例子

在这个例子里面我们定义了三个进程、定义了两个线程

我们可以看到这三个进程之间有依赖关系

进程之间的依赖关系 实际上也就是前面的这个进程会给后面这个进程发消息请求

另外的话 在“课程目录系统访问”这个进程里面

我们又包含或者创建了两个线程

一个是提供缓冲区这样一个线程 另外一个是课程缓冲区这样一个线程

线程和进程之间 因为这两个线程都所属于前面这个进程

所以它们之间的关系是一种组合关系

也就是说 进程是整体 这两个线程都是他的一部分

下面 我们讲一下识别进程的生命周期

我们说每个进程 它是运行态的

也就是说 在软件运行的时候这个进程可能被创建

然后它执行 最终会消亡 所以对进程和线程来讲 它有它的生命周期

对于单进程结构情况下 每一个进程它的生命周期

是当应用被启动或者执行的时候 这个进程它就被创建

当应用执行结束的时候 这个进程被撤销

也就是说 在单进程架构情况下 进程的生命周期和整个应用的生命周期是完全一样的

在多进程架构情况下 在系统启动的时候它会创建一个初始进程

这个初始进程 它会在运行过程中根据需要来创建若干个其它的进程

这样的话 每个进程它有独立的被创建的时间 每个进程也必须单独地被撤销

这是一个例子 在这个例子里边 我们的课程目录系统这样一个进程 它去负责创建课程缓冲区和提供缓冲区后面这两个线程

通过发布两个创建线程的消息

第四步 我们把进程要和他的实现关联起来

我们前面讲 软件的最终设计和实现主要就是子系统和类

那么 他的这些实现构件 必须映射到进程和线程当中去

如何来映射呢 主要考虑这么几个因素

第一个就是进程耦合

进程耦合主要是表现在两个进程之间的通信

而进程的通信则取决于进程内部的类 A进程里边的类、B进程里边的类之间的消息

最终在运行态就表现为两个进程之间的消息通信

所以一般情况下我们希望进程之间的耦合性要低 也就是说两个进程之间的通信要少

第二个 出于性能需求

在进程通信的时候 我们需要消耗大量的系统资源

所以进程间通信越频繁、越多 那么必然的整个系统的响应时间就越慢

另外的话 系统里边的进程数也会对系统的性能有显著影响

我们前面讲 在系统里边多个进程能够提高整个系统的处理器的利用率

能够帮助提高整个系统的性能

但是如果进程数量过多 那么这些进程在操作系统调度的时候

这些调度 它又会消耗相应的CPU资源

所以我们在设计的时候 出于性能的考虑 进程数应该是满足需求的基础上最少

第三点 还要考虑系统的进程和线程的限制

像Windows操作系统、Linux操作系统这样一些操作系统里边

它都定义了系统里边最多能够支持的进程数或者线程数

最后 还要考虑已有的线程和进程的数量以及整个系统里面的IPC(进程间通信)的资源

最后我们讲一下 如何把这些模型元素分配给进程或者线程

我们这里对于一个进程举了一个例子

这是一个主学生进程 它有两个类

一个是主学生的Form表单类 还有一个课程注册的Form表单类

我们通过这样一个图描述这两个类都分配给了当前的这个进程

在系统设计的时候 所有的设计元素 类或者子系统 必须在至少一个进程里边执行

当然了 有些情况下一个类或者子系统也可能会需要在两个进程里边执行

但是不能存在一个类 不存在在任何一个进程里边 这是错误的 或者说是不允许的

在把设计元素分配给进程的时候主要考虑这么几个因素

第一个就是性能和并发性的需求

第二个就是对并行环境的分布式部署的需求

第三个要考虑冗余和可用性的需求

具体分配的时候有两种策略

第一种是从内到外 第二种是从外到内

对于从内到外来讲

我们把设计元素 类和子系统 里边

相互协作比较多、关系比较紧密的分配到同一个进程、同一个线程里边去

反过来 如果两个类或者两个子系统 两个元素 之间是没有交互的

那就应该把它放到不同的进程或者线程里边去

我们重复上面这样一个过程 一直到我们产生最少数量的进程或线程

但同时能够满足系统的非功能性需求

比如说分布式、效率或者是资源利用率这样一些要求

那么第二种 我们说是从外到内

从外到内的话 我们首先对每一个外部事件的响应 定义一个独立的线程和进程

再一个 我们对于每一个独立的服务定义一个独立的进程和线程

然后 我们再来看这些所有的进程和线程

有没有可能对它们进行合并 从而去减少它们的数量

一直到数量可以被系统所支持或者说能够满足系统的要求

好了同学们 今天我们就介绍到这里

我们讲的是运行态体系架构

我们首先分析 在软件系统里边为什么会有并发需求

然后我们介绍了描述并发需求的主要的两个元素 进程和线程

接着我们讲了一下如何来定义进程的生命周期

以及我们前面所识别的设计元素如何把它分配给进程或者线程

以及怎样采用UML图形的方式来描述进程和线程

谢谢大家

面向对象分析与设计课程列表:

面向对象概述

-软件开发过程中的主要问题和好的解决方法

--软件开发过程中的主要问题和好的解决方法

--软件开发过程中的主要问题和好的解决方法

统一软件开发(RUP)

-RUP软件开发模型的特点

--RUP软件开发模型的特点

--RUP软件开发模型的特点

面向对象建模

-四个基本原则

--四个基本原则

--四个基本原则

-对象和类

--对象和类

--对象和类

-类之间的关系

--类之间的关系

--类之间的关系

需求概述

-用例模型

--用例模型

--用例模型

-用例之间的关系

--用例之间的关系

--用例之间的关系

-用例建模

--用例建模

--用例建模

分析与设计概述

-分析与设计概述

--分析与设计概述

--分析与设计概述

架构分析

-架构分析基本概念

--架构分析基本概念

--架构分析基本概念

-定义模型的高层组织结构

--定义模型的高层组织结构

--定义模型的高层组织结构

-确定分析机制、确定关键概念、创建用例实现

--确定分析机制、确定关键概念、创建用例实现

--确定分析机制、确定关键概念、创建用例实现

用例分析概述

-用例分析概述

--用例分析概述

--用例分析概述作业

-控制类

--控制类

--控制类

-用例行为和类的关系

--用例行为和类的关系

--用例行为与类的关系

识别设计类

-识别设计元素概述

--识别设计元素概述

--识别设计元素概述

-识别子系统及接口

--识别子系统和接口

--识别子系统及接口

描述运行态软件体系架构

-描述运行态软件体系架构

--描述运行态软件体系架构

--描述运行态软件体系架构

描述分布式系统架构

-描述分布式系统架构概述

--描述分布式系统架构概述

--描述分布式系统架构概述

用例设计

-用例设计描述

--用例设计描述

--用例设计描述

子系统设计

-子系统设计概述

--子系统设计概述

--子系统设计概述

类设计

-创建初始设计类、定义类操作方法

--创建初始设计类、定义类操作方法

--创建初始设计类、定义类操作方法

-定义类状态

--定义类状态

--定义类状态

-定义类之间的依赖关系、关联关系以及多重性设计

--定义类之间的依赖关系、关联关系以及多重性设计

--定义类之间的依赖关系、关联关系以及多重性设计

-定义类的泛化关系、解决用例冲突、非功能性需求

--定义类的泛化关系、解决用例冲突、非功能性需求

--定义类的泛化关系、解决用例冲突、非功能性需求

描述运行态软件体系架构笔记与讨论

也许你还感兴趣的课程:

© 柠檬大学-慕课导航 课程版权归原始院校所有,
本网站仅通过互联网进行慕课课程索引,不提供在线课程学习和视频,请同学们点击报名到课程提供网站进行学习。