从0开始学架构—架构基础

142 阅读9分钟

软件架构

什么是架构?

我们常听到的 Linux架构、MySQL架构、微信架构、微信登陆系统架构......
架构到底指什么?先了解下架构相关的概念:系统、模块、组件、框架、架构

1. 系统:系统由多个子系统组成,最小子系统包括模块和组件,系统能力不是子系统能力之和,而是产生新的能力

image.png

image.png 2. 模块&&组件:简单理解: 从逻辑角度区分就是“模块”,从物理角度区分就是组件,划分模块目的是职责分离,划分“组件”的目的是单元复用

image.png

3. 框架Framework&&架构Architecture(结构)

框架 是一种组件规范,例如MVCMVPMVVM, 提供基础功能的产品SpringMVC是MVC的开发框架
架构 关注的是结构,“模块”、“对象”、“组件”本质上是对达到一定规模的软件进行拆分,差别只在于随着软件的复杂度不断增加,拆分力度越来越粗,拆分角度越来越高,形成了架构

4. 重新定义架构:指软件系统的顶层结构,系统是由关联的个体组成,这些个体可以时“子系统”、“模块”、“组件”等,其次个体需要“根据某种规则”运作。

软件系统

计算机发展本质由硬件发展驱动的,尤其是CPU性能发展。而将硬件性能充分发挥出来的是操作系统;操作系统是软件系统的运行环境;

冯诺依曼结构:计算机的五大基本构件:运算器、存储器(内存)、输入设备(键盘,鼠标)、输出设备(打印机、显示器)和控制器。USB属于输入/输出设备。计算的硬件均由冯诺依曼结构构成。

image.png

image.png

架构设计的目的

架构主要目的是解决复杂度带来的问题,架构是一种方案之一

软件技术发展史

整个过程分为面向机器、面向过程、面向对象

软件技术发展史.png

如何理解面向对象?

举个例子:如何把大象装进冰箱? 冰箱打开open,关闭:close, 装进去fix。以冰箱定义为class F(), F定义三个方法open,close,fix。以面向过程的思考方式抽象成面向对象的思考方式。

复杂度来源

高性能的追求

技术发展带来了性能的提升,不一定带来复杂度提升。新技术淘汰旧技术,这种情况直接用新技术即可,但若是并不是取代而是开辟全新领域的技术,就会给软件带来复杂度。

软件系统的高性能带来的复杂度主要体现在两方面

  • 单台计算机内部为了高性能带来的复杂度(单机复杂度)
  • 集群复杂度(通过大量机器提升性能)

1. 单机复杂度

将硬件性能充分发挥出来的是操作系统;操作系统是软件系统的运行环境;操作系统的复杂性决定了软件系统的复杂性;操作系统和性能最相关的是进程和线程

image.png

如果要完成一个高性能的软件系统需要考虑如下技术点:多进程、多线程、进程间通信、多线程并发等

2. 集群复杂度

类似于红包 & 支付业务复杂度是单机的性能无法支撑的,必须采用集群。多台机器配合是个复杂的任务。主要解决方案分为任务分配、任务分解。 a. 任务分配 假设单台服务器每秒支持5000次请求,那么两台服务器每秒支持10000次请求,但实际的性能一般按照8折8000次左右折算,随着性能的增高,任务分配器本身又会成为瓶颈。同时状态管理和故障处理的复杂度也会大大增加

image.png

任务分配常见方法:DNS轮询、智能DNS、CDN(内容分发网络)、GSLB设备(全局负载均衡)。
多对多如图:

image.png

以上是以业务处理为样例,实际上“任务”涵盖很广,可以指完整的业务处理、某个具体任务(存、运算、缓存等。任务分配器)可能是物理机器、独立运行的程序、嵌入在其他程序的算法

b. 任务分解

如果业务本身越来越复杂,单纯通过任务分配的方式性能只会越来越低,随着业务复杂度升高,单台机器的性能会越来越低。系统功能越简单,影响性能的点越少。
任务分解后,代码量,和功能都不会少,唯一的区别是代码从内部调用改为服务器之间的接口调用。
可以针对单个业务进行扩展,各个业务分解到独立的子系统后,性能瓶颈更容易被发现,修改风险降低。 但也不能拆的太细,为了完成某个业务,系统之间的调用次数会呈指数型上升。系统间的调用渠道目前是通过网络方式传输,远比函数调用低的多,如果业务本身没有发生大的变化,理论上性能是有一个上限的。系统拆分能让性能逼近这个极限

image.png

高可用

高可用:系统无中断的执行功能,单个硬件/软件都会有故障/bug,本质上无法做到“无中断”。 高可用方案:本质上是通过冗余来实现的。而冗余本质和高性能一样是通过增加机器来达到目的。单其目的不同,高性能增加机器为了“扩展”处理性能,高可用目的在于“冗余”处理单元。

“冗余”增强可用性的同时会增加复杂性。

根据不同场景来分析

1. 计算高可用

image.png

image.png

2. 存储高可用

存储和计算的本质区别在于:数据从一台机器搬到另一台机器需要进行传输,这就意味着数据在某个时间点上,数据肯定是不一致的。

难点不在于备份,而在于如何规避数据不一致对业务造成的影响,分布式领域著名CAP定理从理论上论证了存储高可用的复杂度。高可用不可能同时满足“一致性、可用性、分区容错性”,最多满足两个,这就要求我们做架构个设计时结合业务进行取舍

image.png

3.高可用状态决策

无论计算高可用还是存储高可用,其基础都是状态决策。系统判断当前状态是否异常,然后采取行动保证高可用。如果状态决策本身有偏差,那么后续任何行动和处理都是无意义的。通过“冗余“实现高可用,状态决策就不可能做到完全正确。

image.png

可扩展性

面向对象的提出就是为了解决可扩展性带来的问题,后来的设计模式将可扩展性发挥到了极致。良好的可获粘性包含两个方面预测变化、应对变化

1. 预测变化

“唯一不变的时变化”,如果每个点都要考虑扩展性,架构师会不堪重负,且难以落地。但也不可能不做预测,“预测”意味着不是100%准确的。如何把握预测没有统一的标准,需要凭借经验、直觉。

  • 不能每个设计都考虑扩展性
  • 不能不考虑可扩展性
  • 所有的预测纯在出错的可能性

2. 应对变化

如果准确预测,是否意味着可扩展性很容易实现呢?否!预测和采取方案时两回事。常见方案如下两种架构模型

image.png

无论采取哪种方式玻璃变化层和稳定层,都会带两两个性能相关问题

  • 拆分(不明确),不同的人有不同的理解
  • 需要设计变化层和稳定层之间的接口

对于稳定层来说,接口肯定越稳定越好,对于变化层来说,在有差异的多个实现方式中找出共同点,还要保证新功能加入时不怎么修改,是一件复杂的事情。存储层如何向稳定层提供接口?自适应判断?

常见应对变化的方案时提炼出一个抽象层(稳定的)、和一个实现层(根据业务实现来定制),拿装饰者设计模式举例:规则一旦抽象出来则不能轻易修改

低成本

当我们满足高性能,高可用通常会增加服务器,但底层本恰巧相反。很多时候低成本不会时首要目标。

底成本的复杂度主要体现在:往往只有创新才能达到低成本目标。比如开创全新领域或引入新技术。比如NoSQL解决关系型数据库无法应对高并发访问带来的压力。比如引入新技术,就需要区学习新技术,并且和现有技术结合起来

安全

1.功能安全(代码层,防小偷)

XSS攻击、CSRF攻击、SQL注入、Windows漏洞、密码破解等。功能安全是个逐步完善的过程 2. 架构安全(防强盗)

传统的架构安全主要靠防火墙(隔离网络),将网络划分成不同区域,不同区域控制策略来控制不同信任程度去遇见传送的数据流。功能强大但性能一般,无法应对互联网的高并发。目前更多以来运营商和云服务商的带宽和流量的清洗能力。

规模

代码叠加,量变引起质变。

  • 功能越来越多,导致系统复杂度上升
  • 数据越来越多,系统复杂度发生质变

最近火热的“大数据”由此产生,数据太多,传统的数据收集、加工、存储、分析手段和工具无法适应,需要新技术才能解决

数据库存储,修改耗时、备份时长,拆表,整合数据等