架构设计方法论理解
1.对架构的认识
1.1 架构是什么?
对于技术人员,“架构”是一个很常见的词。 整个系统的架构、架构设计评审、开源系统(mysql、hadoop)的架构、大公司的架构 (微信、淘宝架构) 等。 虽然“架构”这个词常见,但深究一下“架构”到底指什么,大部分人可能不一定能够准确的回答出来,比如:
- 架构和框架什么关系?有什么区别?
- linux有架构、MySQL有架构、微信也有架构、当我们谈到这些架构是,到底在谈什么架构?
要解释这些问题, 首先要搞清楚几个相关而且相似的概念:系统与子系统、模块与组件、框架和架构。
- 系统:一群有关联的组成,根据某种规则运行,能完成个别元件不能单独完成的工作的群体。(整体、总体; 关键词: 关联、规则、能力)
- 子系统:(观察视角的差异) 一个系统可能另外一个更大的系统的子系统;一个系统也可能包含多个子系统
- 模块和组件:(在实际工作中也容易混淆)模块和组件都是系统的组成部分,只是从不同的角度拆分系统。
- 从逻辑角度拆分出来的称作 模块; 划分模块的主要目的是职责分离
- 从物理的角度拆分 的带的组件; 划分组件的目的是 单元复用
举例:一个简单的网站系统(比如学生信息管理系统)。 从逻辑的角度拆分,可以分为“登录注册模块” “个人信息模块”; 从物理的角度拆分,可以拆分为nginx、web服务器、mysql等组件。
组件更多的是体现复用,而模块体现的是系统的逻辑组成.
框架与架构: (比较相似的概念,有较强的的关联关系)
- 框架 是组件规范:例如mvc、mvp、j2ee等; 框架提供基础功能的产品。
- 软件架构:指软件系统的“基础结构”, 创造这些基础结构的准则,以及这些结构的描述
但: 平常经常会遇到一些似是而非的说法。 比如:“我们的系统是MVC架构”, “重构成MVP架构”, “基于SSH框架开发”,“是SSH的架构”
这些说法都是对的,原因在于架构的定义中:“基础结构”这个概念, 并没有明确说 从什么角度来分解,采用不同的角度或者维度,可以将系统分为不同的结构。
比如,学生信息管理系统中,从业务逻辑的角度分解,系统的架构是”有哪些模块,模块之间的关系“;
从物理部署的角度分解, 系统的架构是”用了什么组件,之间的关系(数据流向)“
从开发规范的角度分解,系统采用MVC框架来开发,因此架构又变成了MVC架构,”由Controller、View、Model 组成;之间什么关系(数据流向)”
这些架构, 都是“学生管理系统”正确的架构,只是从不同的角度来分解而已, 这也是IBM的RUP将软件架构视图分为著名的“4+1视图”的原因。
最终的架构定义: 软件架构 指软件系统的顶层结构。 (这个定义看似简单,但把系统、子系统、组件、模块、架构等概念都串起来了, 包含的信息丰富)
1.2 怎么学习架构设计
我们工作中见到过很多架构设计,也做过一些架构设计。 但是我们做的好不好呢,很多人尤其开发人员做的系统上线后才发现很多设计上的问题,没有系统的规划和解决。
是因为 没有系统化的 架构设计思想和能力。 没有完整的从头到尾,从需求分析、软件系统的复杂度分析,到详细设计和时间 完整的结合业务场景做系统设计。
不管是我们遇到的 各个领域的架构 比如搜索架构、安全风控架构, 还是其中的数据架构、子系统架构。
其实最重要的是 结合实际业务场景,搞清楚架构设计的目的了;学习系统的架构设计方法和思路; 实践总结经验。
tips:了解架构模式及技术的发展历程, 在什么背景下出现,解决了什么问题。 无论是在平常的工作还是系统架构设计中,最重要的是发现和识别清楚问题。
解决问题的方法有很多。其次是选择合适的方法(合适的架构模式和技术)
2.架构设计的历史背景
2.1 结构化程序设计
20 世纪 60 年代 ,高级语言的出现后,随着软件的规模和复杂度的大大增加,60年代中期出现一些软件危机。 典型表现有软件质量低下、项目无法如期完成、项目严重超支等,因为软件而导致的重大事故时有发生。(1963 年美国的水手一号火箭发射失败事故, 由于一行FORTRAN代码错误导致)
大型软件项目的延期、成本超支,结构化程序设计方案应运而生。
结构化程序设计的主要特点是抛弃 goto 语句,采取“自顶向下、逐步细化、模块化”的指导思想。结构化程序设计本质上还是一种面向过程的设计思想,但通过“自顶向下、逐步细化、模块 化”的方法,将软件的复杂度控制在一定范围内,从而从整体上降低了软件开发的复杂度。结构 化程序方法成为了 20 世纪 70 年代软件开发的潮流。
2.2 面向对象程序设计
然而随着硬件的快速发展,业务需求越来越复杂,以及编程应用领域越来越广泛,第二次软件危机很快就到来了。
根本原因还是在于软件生产力远远跟不上硬件和业务的发展。
第一次软件危机的根源在于软件的“逻辑”变得非常复杂,而第二次软件危机主要体现在软件的“扩展”变得非常复杂
- 结构化程序设计虽解决或者缓解了软件逻辑的复杂性;面向对象解决业务变化带来的软件扩展。
面向对象真正开始流行是在 20 世纪 80 年 代,主要得益于 C++ 的功劳,后来的 Java、C# 把面向对象推向了新的高峰。
第二次软件危机促进了面向对象的发展。
2.3 软件架构的历史背景
流行在 20 世纪 90 年代开始
随着软件系统规模的增加,计算相关的算法和数据结构不再构成主要的设计问题;当系统由许多部分组成时,整个系统的组织,也就是所说的“软件架构”,导致了一系列新的设计问题。
- 系统规模庞大,内部耦合严重,开发效率低;
- 系统耦合严重,牵一发动全身,后续修改和扩展困难;
- 系统逻辑复杂,容易出问题,出问题后很难排查和修复。
随着软件规模的发展,不同时期产生了 “结构化编程”、“”模块,“面向对象编程”、“对象”,“软件架构”、“组件”。
我们可以看 到,“模块”“对象”“组件”本质上都是对达到一定规模的软件进行拆分,差别只是在于随着 软件的复杂度不断增加,拆分的粒度越来越粗,拆分的层次越来越高。
3. 架构设计的目的
很多人对架构设计的真正目的还是比较模糊。 先来看几个问题:
做了架构设计就能提升开发效率么?
设计良好的架构能促进业务发展么?
不是每个系统都要做架构设计吗
为了高性能、高可用、可扩展,所以要做架构设计? 但不是所有的系统都需要高性能、高可用。
那架构设计的真正目的是什么呢?
从架构设计的历史背景看,整个软件技术发展的历史,其实就是一部与“复杂度”斗争的历史,架构的出现也不例外。 简而言之,架构也是为了应对软件系统复杂度而提出的一个解决方案
3.1 系统复杂度
架构设计的目的架构 是为了解决软件系统复杂度带来的问题。 (回顾架构产生的历史背景和原因)
结论虽然简洁,但却是架构设计过程中需要时刻铭记在心的一条准则.
3.2 做架构设计的理解
通过熟悉和理解需求,识别系统复杂性所在的地方,然后针对这些复杂点进行架构设计。
架构设计并不是要面面俱到,不需要每个架构都具备高性能、高可用、高扩展等特点,而 是要识别出复杂点然后有针对性地解决问题。
理解每个架构方案背后所需要解决的复杂点,然后才能对比自己的业务复杂点,参考复杂 点相似的方案。
如果系统的复杂度不是在性能这部分,TPS 做到 10 万并没有什么用。
淘宝的架构是为了解决淘宝业务的复杂度而设计的,淘宝的业务复杂度并不就是我们的业 务复杂度,绝大多数业务的用户量都不可能有淘宝那么大。
Docker 不是万能的,只是为了解决资源重用和动态分配而设计的,如果我们的系统复杂度 根本不是在这方面,引入 Docker 没有什么意义。
3.3 复杂度来源
3.3.1 高性能
软件系统中高性能带来的复杂度主要体现在两方面,一方面是单台计算机内部为了高性能带来的复杂度;另一方面是多台计算机集群为了高性能带来的复杂度。
单机复杂度
计算机内部复杂度最关键的地方就是操作系统。
操作系统和性能最相关的就是进程和线程。
为了解决手工操作带来的低效,批处理操作系统应运而生。
为了进一步提升性能,人们发明了“进程”,用进程来对应一个任务,每个任务都有自己独立的 内存空间,进程间互不相关,由操作系统来进行调度。
多进程虽然要求每个任务都有独立的内存空间,进程间互不相关,但从用户的角度来看,两个任务之间能够在运行过程中就进行通信,会让任务设计变得更加灵活高效。集群的复杂度
虽然计算机硬件的性能快速发展,但和业务的发展速度相比,还是小巫见大巫了,尤其是进入互联网时代后,业务的发展速度远远超过了硬件的发展速度。任务分配
任务分解
简单的系统更加容易做到高性能
可以针对单个任务进行扩展
3.3.2 高可用
计算高可用
存储高可用
高可用状态决策
- 独裁式:独裁式决策指的是存在一个独立的决策主体,我们姑且称它为“决策者”,负责收集信息然后进行决策;所有冗余的个体,我们姑且称它为“上报者”,都将状态信息发送给决策者。
- 协商式:协商式决策指的是两个独立的个体通过交流信息,然后根据规则进行决策,最常用的协商式决策就是主备决策。
- 民主式:民主式决策指的是多个独立的个体通过投票的方式来进行状态决策。例如,ZooKeeper 集群在 选举 leader 时就是采用这种方式。
3.3.3 可扩展性
业务需求、运行环境方面的变化都会导致软件系统发生变化,而这种软件系统对上述变化的适应能力就是可扩展性。
预测变化
应对变化
3.3.4 低成本、安全、规模
4. 架构设计三原则
系统架构设计原则
合适原则:“合适优于业界领先”
简单原则:“简单优于复杂” (结构的复杂性、逻辑的复杂性)
演化原则:“演化优于一步到位”
其他原则:高可用原则、可扩展性、可维护性、松耦合原则、性能优化原则、安全性原则、可测试性原则、成本效益原则、一致性原则.
4.1 合适
领先的技术方案可能并不完全适配特定系统的实际需求、技术能力、预算限制、维护能力、以及业务发展阶段等因素。
例如:一个小型企业的内部管理系统,如果强行采用业界领先但复杂且昂贵的架构,可能会导致资源浪费、维护困难,反而不如选择一个简单、实用且适合其规模和业务特点的架构
4.2 简单
简单的架构有以下优点:
- 易于理解:开发团队成员能够更快速、更清晰的理解系统的整体结构和工作原理,降低沟通成本和理解偏差。
- 易于维护:简单的架构减少了组件之间的交互复杂性,使得故障排查、修复和系统更新更容易运行,降低了维护成本和风险。
- 提高开发效率:开发人员可以更高效地进行编码和测试,减少因为复杂逻辑导致的错误和延误。
- 曾强可靠性:简单的架构通常具有更少的潜在故障点和意外情况。
- 便于扩展:简单的基础架构在添加新功能或模块时,更容易进行规划和整合,不会因为复杂的现有结构而受到过多限制。
4.3 演化
演化意味着随着时间的推移,根据业务需求的变化,技术的发展以及用户的反馈逐步改进和完善。这种方式具有以下优点:
- 降低风险:避免在一开始就涉及一个过于庞大和复杂的架构,减少了由于前期规划不准确或考虑不周全导致的重大错误
- 更好的适应变化:业务需求和技术环境通常是不断变化的。 通过演化的方式,架构能够更灵活地适应这些变化,而不是被最初的”一步到位“的设计所束缚。
- 成本效益:逐步投入资源进行改进和扩展,相比一次投入大量资源构建一个可能不完全符合实际需求的架构,更加经济高效。
- 增加学习和改进的机会,在演化过成汇总,团队能够不断积累经验,发现问题并及时调整,从而使架构越来越优化。
4.4 其它原则
4.5 系统架构设计原则案例
5. 架构设计流程
识别复杂度
设计备选方案
评估和选择备选方案
详细方案设计