当前位置:网站首页>软件架构介绍
软件架构介绍
2022-06-21 20:24:00 【夜雨风云】
架构显然很重要。许多开发人员的目标是成为一名架构师。但什么是架构,为什么架构如此重要?为了回答这个问题,这里首先定义软件架构的含义。然后,讨论应用程序的架构是多维的,并使用一组视图或蓝图进行描述。接着,本文将强调软件架构的重要性,因为它对应用程序的质量有显著的影响。
软件架构的定义
架构(Architecture) 一词来源建筑领域,鉴于软件工程和建筑工程一样是一项系统的工程性工作,在引入计算机领域后,软件架构就成为描述规划设计技术的专有名词。
1972年图灵奖获得者(计算机领域的诺贝尔奖)、荷兰计算机科学家Edsger Dijkstra(最短路径算法的发明者)早在二十世纪六十年代(计算机诞生没多久)就已经提及软件架构这个概念了。到了二十世纪九十年代,众多学者和专家都对软件架构做过定义,但都没有一个统一的定义。这里选用卡耐基梅隆大学软件工程研究所的Len Bass及其同事对软件架构的定义,他们在使用软件架构成为一门学科方面发挥了关键作用。该定义是:
Software architecture refers to the fundamental structures of a software and the discipline of creating such structures and systems.
Each structure comprises software elements, relations among them, and properties of both elements and relations.
计算机系统的软件架构是构建这个系统所需要的一组结构和规则,包括软件元素、它们之间的关系以及两者的属性。
上面的描述显然太过抽象。但其本质是将应用程序的架构分解为元素(element)和这些元素之间的关系(relation)。由于以下两个原因,分解很重要:
(1) 它促进了劳动和知识的分工。它使具有特定专业知识的人员或团队能够高效地协同工作。
(2) 它定义了软件元素的交互方式。
将软件分解成元素以及定义这些元素之间的关系,决定了软件的能力。简单来说,软件架构是一个用于指导系统实现的草图,这个草图越详细,对系统实现的指导意义就越重要,且贯穿于软件的整个生命周期。
软件架构的4+1视图模型
为了清晰的描述软件架构的设计,这里引入“架构视图”。架构视图是由 Philippe Kruchten 在其著作的《Rational统一过程引论》中定义:
一个架构视图是对于从某一视角或某一点上看到的系统所做的简化描述,描述中涵盖了系统的某一特定方面,而省略了与此方面无关的实体。
也就是说,可以从不同视角描述同一个软件架构,最后这多个视角构成了完整的软件架构。那么哪些视角可以作为全面描述一个系统架构的最核心视图?1995年,Philippe Kruchten 在IEEE Software上发表了"4+1视图模型"(The 4+1 View Model of Architecture),正式提出可以使用场景视图、逻辑视图、实现视图、进程视图和部署视图等五个方面来描述软件架构。该划分后来也成为软件架构设计的标准。视图模型的关系如下:
(1) 逻辑视图。开发人员创建的软件元素。在面向对象的语言中,这些元素是类和包。它们之间的关系是类和包之间的关系,包括继承、关联和依赖。通常在UML中用类图、交互图、时序图等来描述。
(2) 实现视图。也叫开发视图。构建编译系统的输出。此视图由表示打包代码的模块和组件构成。在Java中,模块是JAR文件,组件通常是WAR文件或可执行JAR文件。它们之间的关系包括模块之间的依赖关系以及组件和模块之间的组合关系。在UML中用组件图、包图来表述。
(3) 进程视图。运行时的组件。每个元素都是一个进程,进程之间的关系代表进程间通信。进程视图和开发视图的关系:开发视图一般偏重程序包在编译时期的静态依赖关系,而程序运行起来后,则表现为对象、线程、进程,进程视图关注这些元素的交互问题。在UML中通常用活动图来表述。
(4) 部署视图。也叫物理视图。进程如何映射到机器。此视图的元素由计算机(物理机或虚拟机)和进程组成。机器之间的关系代表网络。该视图还描述了进程和机器之间的关系。部署视图关注软件的物理拓扑解耦股已经如何部署机器和网络来配合软件系统的可靠性、可用性、弹性等要求。部署视图是综合考虑软件系统和整个IT系统相互影响的架构视图。
(5) 场景。关注最终用户需求,为整个软件架构的上下文,通常由UML用例图或活动图描述。场景负责把视图串联在一起。每个场景负责描述在一个视图中的多个架构元素如何协作,以完成一个请求。例如,在逻辑视图中的场景,展示了类是如何协作的。
软件架构重要性
应用程序有两个层面的需求。第一类是功能性需求,这些需求决定一个应用程序做什么。这些通常都包含在用例(user case)或用户故事(user story)中。应用的架构其实跟这些功能性需求没什么关系。功能性需求可以通过任意架构实现,甚至是非常糟糕的大泥球架构。
架构的重要性在于,它帮助应用程序满足了用户的第二类需求:非功能性需求。这类需求也常常被称之为质量属性的需求,或者简称为"能力"。这些非功能性需求决定一个应用程序在运行时的质量,比如可扩展性和可靠性。它们也决定了运行时的质量,如可靠性、可用性和弹性等。它们也决定了设计时的质量,包括可维护性、可测试性、可扩展性和可部署性等。为应用程序所选择的架构将决定这些质量属性。
架构风格
每种软件架构方式、每个具体系统所体现的架构设计,都可以被工程师理解,进而提炼出一些架构思想和设计原则,这种思想和原则就是这种架构方式的风格。依据这些风格,可以对各种架构进行划分,从而进一步讨论每种架构风格的特点。
特定的架构风格提供了有限的元素(组件)和关系(连接器),架构师可以从中定义应用程序的视图。应用程序通常使用多种架构风格的组合。
分层架构风格
典型的架构风格是分层架构。分层架构将软件元素按照"层"的方式组织。每层都有明确的定义和职责。分层架构还限制了层之间的依赖关系。每一层只能依赖于紧邻其下的层次或其下面的任何层。虽然没有明确约定,软件一定要分成几层,但是四层的结构是最常见的。
这里,表现层(presentation)负责用户界面,负责视觉和用户互动,业务层(business)负责实现业务逻辑,持久层(persistence)负责提供数据,SQL 语句就放在这一层,数据库(database)负责保存数据。有的软件在逻辑层和持久层之间,加了一个服务层(service),提供不同业务逻辑需要的一些通用接口。
单体架构风格
单体架构最大的特点是整个系统的所有功能单元整体部署到同一个进程(所有的代码可以打包成一个或多个文件)中。在最初的单体架构中,所有的代码全部都在一个项目中。后来,随着代码规模的扩大,又演化出基于模块、组件、前后端分离等多种演化版本。但是对单体架构来说,存在以下问题:
(1) 代码存在严重耦合的问题。修改一处代码,可能影响一大片的功能无法正常使用。为了保障每次上线时的可靠性,必须花费大量的精力做回归测试。对于需要经常修改维护的系统,这种代码是可怕的。
(2) 系统变更对部署影响大。系统作为一个整体部署,每次发布的部署单元即使一个新版本的系统。系统内的任何业务变更都会导致整个系统的重新打包、部署、停机、重启。而且每次发布上线都是生产系统的重大变更,这种部署模式大大增加了整个系统的风险,降低了系统的可用性。
(3) 影响开发效率。当代码规模超过100万行时,一次编译可能要等待数十分钟以上,而且代码执行时,对内存的要求也很高。如果仅是几行或几十行代码的修改,一次验证要等待这么长时间,其开发效率是难以想象的。
(4) 启动时间过长,影响系统的可用性。由于所有的代码都在一个进程中执行,所以随着代码规模的增长,其启动时间也会越来越长,从而影响系统的可用性。
(5) 扩展性受限。任何一个功能点存在性能问题,都会影响整个系统的可用性。如新增的一个功能点引入了内存泄露问题,则会导致整个系统可用性降低。或者新增的一个功能点需要更多的内存,则需要增加整个系统的内存。在多实例场景下,这会带来不必要的内存浪费。
微服务架构风格
微服务架构是一种分布式架构,使用更细粒度的服务和一组设计准则来应对大规模的复杂系统架构设计问题。微服务架构的实现视图由多个组件构成。它的组件是服务,连接器是使这些服务能够协作的通信协议。每个服务都有自己的逻辑视图,如六边形架构、洋葱架构、DDD架构等。更多微服务架构介绍可参考笔者之前的文章。
微服务架构是面对单体应用规模逐渐变大的解决之道,但是事物都是一体两面的,微服务架构也存在诸多陷阱,并不是简单拿来用就可以的。所以在大规模使用微服务时,不仅要从思想和业务上进行合理划分,还需要诸多技术组件,以及高效的运维支撑。常见的问题有:
(1) 熔断。当请求依赖的上游服务时发生一定数量的失败后,熔断器打开,接下来的请求快速返回失败。过一段时间后,重新检查上游服务是否已恢复正常,重置熔断器。
(2) 超时。超时设置对于调用服务来说非常重要,超时设置时间太长可能会把整个系统拖慢,而设置超时过短又会造成调用服务未完成而返回,在实际工作中,要根据业务场景进行分析,选择一个恰当的超时阈值。
(3) 幂等。在提供接口时,要考虑接口的幂等性,避免重复请求引入的业务问题。
(4) 可伸缩性。当并发量较大时,原有服务集群无法满足现有业务场景时,可以采用扩容策略,当并发量较小时,可以采用缩容策略,以节省资源。
这里仅介绍微服务架构带来的一些常见问题,后面还会编写专门的文章探讨微服务治理。
参考
https://www.zhihu.com/question/307196183/answer/2257587835 软件架构是什么
http://ruanyifeng.com/blog/2016/09/software-architecture.html 软件架构入门
微服务架构设计模式 Chris Richardson 著, 陈斌 等 译
高可用可伸缩微服务架构 程超 梁桂钊 秦金卫 方志斌 张逸 等著
边栏推荐
- Fu · new life, chain · future! The conference on enabling innovation and development of urban chain technology industry was held grandly
- C#的DataGridView中字体大小
- 杠铃策略--极稳极浪不内卷
- Luogu p1514 [noip2010 improvement group] water diversion into the city
- Communication failure between botu simulation HMI and real 1200plc
- How C # aboutbox displays its defined interface
- 广东疾控提醒:暑期将至,返粤大学生这样安全“归巢”
- 大型语言模型教会智能体进化,OpenAI这项研究揭示了二者的互补关系
- InstaDeep Ltd:Arthur Flajolet | 单机上基于群体的快速强化学习
- IQtree|构建进化树的软件
猜你喜欢

Chess and card games

solidity实现智能合约教程(4)-ERC1155合约

leetcode刷题:顺丰科技智慧物流校园技术挑战赛

Leetcode508- the most frequent subtree elements and - deep search

Fu · new life, chain · future! The conference on enabling innovation and development of urban chain technology industry was held grandly

企业数据防泄漏解决方案分享

2022佛山潭洲陶瓷展召开新闻发布会 推出展会十大重点

C# AboutBox怎么显示自己定义的界面
Go language unit test basics from getting started to giving up

中国工程院院士郑纬民:我对中国在下一个 IT 时代拥有一席之地很乐观
随机推荐
16 iterator classic case
Huawei Hongmeng development lesson 3
Zhengweimin, academician of the Chinese Academy of Engineering: I am optimistic that China will have a place in the next it Era
Communication failure between botu simulation HMI and real 1200plc
Chess and card games
Worthington胶原蛋白酶原料
In the anchoring stage of retail digitalization, more attention is paid to how to mine and transform traffic by means of Digitalization
JS异步的执行顺序是什么
洛谷P1378 油滴扩展 题解
博图仿真HMI与真实1200PLC通讯失败
Characteristics and experimental suggestions of abbkine cell cycle Staining Kit
对“XXX::Invoke”类型的已垃圾回收委托进行了回调。这可能会导致应用程序崩溃、损坏和数据丢失。向非托管代码传递委托时,托管应用程序必须让这些委托保持活动状态,直到确信不会再次调用它们
New energy industry commercial procurement collaboration system: enable new energy industry procurement business and enhance industrial collaboration
Worthington弹性蛋白酶背景和特异性介绍
GAMES101作业7-多线程提速实现步骤详解
InteliJ-IDEA-高效技巧(二)
Utilisation de la combinaison d'assertions de l'API Stream et de la mise en cache locale pour les requêtes floues (près de 1000 fois plus efficace que MySQL)
solidity实现智能合约教程(4)-ERC1155合约
Summary of internship interview experience of more than ten failed internship positions
mafft|多序列比对工具