架构设计方法论理解

Catalogue
  1. 1.对架构的认识
    1. 1.1 架构是什么?
    2. 1.2 怎么学习架构设计
  2. 2.架构设计的历史背景
    1. 2.1 结构化程序设计
    2. 2.2 面向对象程序设计
    3. 2.3 软件架构的历史背景
  3. 3. 架构设计的目的
    1. 3.1 系统复杂度
    2. 3.2 做架构设计的理解
    3. 3.3 复杂度来源
      1. 3.3.1 高性能
      2. 3.3.2 高可用
      3. 3.3.3 可扩展性
      4. 3.3.4 低成本、安全、规模
  4. 4. 架构设计三原则
    1. 4.1 合适
    2. 4.2 简单
    3. 4.3 演化
    4. 4.4 其它原则
    5. 4.5 系统架构设计原则案例
  5. 5. 架构设计流程
  6. 不同的架构分类

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 简单

简单的架构有以下优点:

  1. 易于理解:开发团队成员能够更快速、更清晰的理解系统的整体结构和工作原理,降低沟通成本和理解偏差。
  2. 易于维护:简单的架构减少了组件之间的交互复杂性,使得故障排查、修复和系统更新更容易运行,降低了维护成本和风险。
  3. 提高开发效率:开发人员可以更高效地进行编码和测试,减少因为复杂逻辑导致的错误和延误。
  4. 曾强可靠性:简单的架构通常具有更少的潜在故障点和意外情况。
  5. 便于扩展:简单的基础架构在添加新功能或模块时,更容易进行规划和整合,不会因为复杂的现有结构而受到过多限制。

4.3 演化

演化意味着随着时间的推移,根据业务需求的变化,技术的发展以及用户的反馈逐步改进和完善。这种方式具有以下优点:

  1. 降低风险:避免在一开始就涉及一个过于庞大和复杂的架构,减少了由于前期规划不准确或考虑不周全导致的重大错误
  2. 更好的适应变化:业务需求和技术环境通常是不断变化的。 通过演化的方式,架构能够更灵活地适应这些变化,而不是被最初的”一步到位“的设计所束缚。
  3. 成本效益:逐步投入资源进行改进和扩展,相比一次投入大量资源构建一个可能不完全符合实际需求的架构,更加经济高效。
  4. 增加学习和改进的机会,在演化过成汇总,团队能够不断积累经验,发现问题并及时调整,从而使架构越来越优化。

4.4 其它原则

4.5 系统架构设计原则案例

5. 架构设计流程

识别复杂度
设计备选方案
评估和选择备选方案
详细方案设计

不同的架构分类