概念
系统
系统泛指由一群有关联的个体组成,根据某种规则运作,能完成个别元件不能单独完成的工作的群体。它的意思是“总体”“整体”或“联盟”。
子系统
子系统也是由一群有关联的个体所组成的系统,多半会是更大系统中的一部分
模块
软件模块(Module)是一套一致而互相有紧密关连的软件组织。它分别包含了程序和数据结构两部分。现代软件开发往往利用模块作为合成的单位。模块的接口表达了由该模块提供的功能和调用它时所需的元素。模块是可能分开被编写的单位。这使它们可再用和允许人员同时协作、编写及研究不同的模块
组件
软件组件定义为自包含的、可编程的、可重用的、与语言无关的软件单元,软件组件可以很容易被用于组装应用程序中
框架
软件框架(Software framework)通常指的是为了实现某个业界标准或完成特定基本任务的软件组件规范,也指为了实现某个软件组件规范时,提供规范所要求之基础功能的软件产品。
软件架构
软件架构指软件系统的“基础结构”,创造这些基础结构的准则,以及对这些结构的描述
逻辑架构
做一个学生信息管理系统,这个系统从逻辑的角度来拆分,可以分为“登录注册模块”“个人信息模块”“个人成绩模块”;
物理架构
做一个学生信息管理系统,从物理的角度来拆分,可以拆分为 Nginx、Web 服务器、MySQL
架构师-业务架构师
从业务角度去分析架构整个系统
架构师-技术架构师
从技术维度分析架构整个系统
总结
- 架构是顶层设计
- 框架是面向编程或配置的半成品
- 组件是从技术维度上的复用
- 模块是从业务维度上职责的划分
- 系统是相互协同可运行的实体
历史背景
- 机器语言(1940 年之前)
- 汇编语言(20 世纪 40 年代)
- 高级语言(20 世纪 50 年代)
- 第一次软件危机与结构化程序设计(20 世纪 60 年代~20 世纪 70 年代)
- 第二次软件危机与面向对象(20 世纪 80 年代)
- 《人月神话》
架构目的
主要目的是为了应对软件系统复杂度而提出的一个解决方案,这个方案需要具备高性能、高可用、可拓展、安全性、还要考虑成本
是在一个有多种约束的条件下求一个最优解,
这个有约束的盒子是团队经验、成本、资源、进度、业务所处阶段等所编织、掺杂在一起的综合体(人,财,物,时间,事情等)
需求驱动架构。在分析设计阶段,需要考虑一定的人力与时间去”跳出代码,总揽全局”,为业务和IT技术之间搭建一座”桥梁”。 架构设计处于软件研制的前期,一方面,越是前期,如有问题,就能够越早发现,修改的代价也就越低;另外一方面,也意味着,软件实施后期若有架构上的修改,也需要付出更多的代价。
复杂度来源:高性能
1)先说性能:
评价一个系统的性能有一系列指标,如RT(响应时间),QPS(服务器每秒处理查询次数),TPS(服务器每秒处理的事务数),
吞吐量等。
2)再说高: 其实这个高性能指的是在某个范围内(一定的用户量,一定的数据量等),各项指标处于一个良好的状态。
3)如何提高性能
- 垂直维度(通过软硬件升级提升单机性能)
- 更换为固态硬盘(SSD)提升I/O访问速度
- 增大内存减少I/O操作
- 使用RAID增加I/O吞吐能力
- 置换服务器获得更多的处理器或分配更多的虚拟核
- 升级网络接口或增加网络接口
- 水平维度(主要针对集群系统,利用合理的任务分配与任务分解实现性能的提升)
- 功能分解:基于功能将系统分解为更小的子系统
- 多实例副本:同一组件重复部署到多台不同的服务器
- 数据分割:在每台机器上都只部署一部分数据
垂直维度适合业务早期阶段,是提升性能最直接的方式,但是受成本和硬件性能的天花板限制
水平维度适合到达一定的业务量,通过垂直提升不能得到很好的改善,但对技术团队也有更高的要求,没有天花板
4)高性能带来的问题
- 单机复杂度:是单台计算机内部为了高性能带来的复杂度
- 集群复杂度:多台计算机集群为了高性能带来的复杂度
复杂度来源:高可用
1)先说可用性
系统服务不中断运行时间占实际运行时间的比例
2)在说高
有很多大公司标准都是4个9,即99.99%,每年系统不可用时间为52.56分钟
但很多公司只能达到3个9,即99.9%,每年系统不可用时间为8.76小时
故障时间秒数=(1-可用性) * 365 * 24 * 3600
3)服务不可用原因
- 硬件故障
- 软件bug
- 不可抗拒力。如地震、水灾、战争等
5)如何做到高可用
核心思想:服务与数据的冗余备份与失效转移
- 服务集群
- 通同城双活
- 异地多活+流量隔离
复杂度来源:可拓展性
1)程序拓展性
预测业务,做出合理的设计,要对扩展开放,对修改关闭
方案:将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”
或者 提炼出一个“抽象层”和一个“实现层”
2)服务伸缩性
系统通过增加服务群节点的方式,提高系统整体业务吞吐能力
方案:
a)消息队列构建生产者消费者模式
b)使用分布式服务构建可复用的业务平台
复杂度来源:低成本、安全、规模
架构三原则
- 合适原则
- 简单原则
- 演化原则
架构设计流程
第一步,识别复杂度
要学会分析整个系统的瓶颈,系统优化时候的关键问题点
第二步,备选方案
- 设计合适方案
- 备选方案不用过于详细,3-5个为最佳
- 备选方案差异要明显
评审会前要和主要相关负责人进行方案沟通
第三步,评估和选择备选方案
360环评:列出我们需要关注的质量属性点,将质量属性按照优先级排序,分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案
常见的方案质量属性点有:
- 性能
- 可用性
- 硬件成本
- 项目投入
- 复杂度
- 安全性
- 可扩展性
第四步,详细方案设计
出设计文档
高性能数据库
读写分离
1)原理:将数据库的读写操作分散到不同的节点上
2)使用场景
- 并发量大,单机已经不能出来该数量的并发请求
- 读远大于写
- 数据实时性要求不严格的业务
3)实现方式
①程序代码封装
在业务层和数据库集群层之间封装一个数据访问层,这样做的特点:
- 实现简单,可以根据业务做较多的定制功能
- 每种编程语言都需要自己实现一份,不能复用,如果一个业务包含多个编程语言写的多个子系统,则重复开发工作量比较大
- 故障情况下,如果主从发生切换,则可能所有系统都修改配置并重启
目前开源方案有
- 淘宝的TDDL(外号:头都大了)
- Sharding-JDBC
②中间件封装
指独立一套系统出来,实现数据库的读写操作,对业务服务提供SQL兼容的协议,
业务服务器直接访问中间件,感觉和连接数据库一样,数据库中间件的特点:
- 支持多种语言,因为提供的是标准SQL接口
- 中间件要时间完整的SQL语法和数据库服务协议,复杂,细节多,容易出现bug
- 所有数据库的请求都需要经过中间件,对性能要求高
- 应用服务对主从切换无感知,数据库中间件可以探测数据库的主从状态,如向某个测试表写入数据,成功的就是主库,失败的就是从库
目前开源的数据库中间件有
- MyCat
- MySQL官方推荐的MySQL Router
- 360开源的Atlas
4)引入的系统复杂度问题
问题一:存在复制延迟
解放方案:
①写操作后的 [读] 操作指定发给数据库主服务器(主要采用拦截器的方式实现)
②读从机失败后再读一次主机(通常说的二次读),二次读的缺点在于如果有大量二次读的请求, 将大大增加主机的负担,有可能造成宕机
③关键业务的读写操作全部指向主机,非关键业务采用读写分离
问题二:存在主从复制延迟
如何将读写操作分开,然后访问不同的数据库服务器