第一章 架构基础
模块与组件
模块:从逻辑角度拆分,主要目的是职责分离
组件:从物理角度拆分,主要目的是单元复用
框架与架构
框架:组件规范(开发规范),提供基础功能的产品。
架构:对软件系统结构的描述
架构设计的目的是什么?
软件架构的历史
- 第一次软件危机——结构化程序设计登场
2000名程序员历时一年,花费原子弹1/4的投入,生产100w行代码。最终以失败告终。
- 第二次软件危机——面对对象 软件扩展能力不足,生产力跟不上硬件和业务的发展。
- 软件架构
随着软件系统规模增加,当系统由许多部分组成时,整个系统的组织,导致了一系列的新的设计问题。
只有规模较大的软件系统会面临软件架构的问题
- 系统规模庞大,内部耦合严重
- 修改和扩展困难
- 逻辑复杂,问题难以排查和修复
【人力总会有局限,当自身的能力不足以应对问题时,除了学习之外,也应该思考是否不是自己的问题,而是问题本身超过了人类的局限】
架构设计的目的
整个软件开发的历史,就是一部与复杂度斗争的历史。
而架构设计的主要目的就是为了解决复杂度带来的问题。
复杂度来源
- 高性能
电子管,晶体管到集成电路,复杂度难以估量。但这种复杂度在选择方面几乎不用考虑,因为没有人会去选择购买电子管计算机。
但是对于不同的出行方式,自行车,公交,火车,高铁,飞机,出行前我们都会根据距离,费用等略作判断。时代的背景下,飞机的出现并没有取代火车,自行车等工具,但从现代计算机的应用来说,电子管已经被淘汰了。
而软件架构就是在一次旅行中,选择最高性价比的方案。
在软件系统中,对高性能需求的复杂度体现在单台计算机为了高性能带来的复杂度和多台计算机集群为了高性能带来的复杂度。
- 单机复杂度 操作系统的多进程,多线程,进程通信,多线程并发等等。 Redis采用单进程,Nginx可以用多进程。具体使用需要结合业务来分析。
- 集群复杂度
- 任务分配:使用多台机器,每台机器都可以处理完整的业务,但会设计到任务分配器,比如硬件F5,软件Nginx等等。 随着机器增多,任务分配器的任务就会加重,成为新的性能瓶颈。这个时候就需要集群式的任务分配器。
- 任务分解:将系统拆分成更小的组成部分,部署到不同的服务器中
任务分配可以突破单台计算机的瓶颈,但持续的增加机器的效率会越来越低。
任务分解换了一种思路,将系统分解,有针对的扩展。
优点:
- 简单系统更加容易有针对性的优化,排错
- 可以对单个部分进行扩展,有的放矢
问题:
- 系统间调用资源消耗
总结: 任务分解和任务分配一样,有一个度,超过这个度,性能反而下降。
- 高可用:系统无中断的执行功能
本质上通过冗余来实现高可用。
冗余:就好像买电瓶车,一次买十辆,第一辆被偷了骑第二辆,第二辆被偷了骑第三辆,依次类推。
- 计算高可用 集群配置,同时有任务分配的瓶颈
- 存储高可用 存储集群。但会产生数据传输的一致性问题。
- 可扩展(靠经验)
- 预测变化
- 应对变化
- 低成本 低成本和高可用,高性能是冲突的。 引入新技术,创造新技术。
- 安全
第二章 架构设计原则
架构与编程的鸿沟:不确定性。
编程是确定的,不管采用何种方式,执行结果都是肯定的。
而不同的架构可能会产生相同的结果。
合适原则
合适优于业界领先。
优秀的架构都是在企业当前人力,条件,业务等各种约束下设计出来的。(生搬硬套不可取)
简单原则
简单优于复杂。
长城的宏伟,悉尼歌剧院的艺术感,”复杂“在制造领域代表先进,在建筑领域代表领先,但在软件领域代表问题。
为什么软件的复杂会带来问题???
除了软件开发的复杂性之外,软件在投入使用后,需要不断变化。没听说过长城不断拆了重建吧。
演化原则
演化优于一步到位。
对于建筑来说,永恒是主题;而对于软件来说,变化才是主题。
软件架构更像是一个人类的进化史:
- 首先,需要适应环境活下来(突然想到了初中历史书上的山顶洞人)恶劣的环境需要大量的体毛来保持身体的恒温
- 在不断的发展中,开始制造工具,开始生火抵抗寒冷
- 再到后来,建房子,用动物皮毛保暖
- 于是体毛渐渐退化,也不再吃生肉
- 生存的方式也从打猎变成更加细分的职业
- 到如今的互联网商业繁荣,大脑思考更加复杂的软件架构 类比软件架构:
- 首先,设计出来的产品可以满足当前业务需要
- 之后在实际的应用中迭代,保留优秀设计,剔除无用设计,增加必要设计
- 最好,当业务发生巨大改变,性能要求更高时,架构要面临扩展,重构;甚至代码语言会发生变化,但在演变过程中的经验,逻辑,设计等会在新的架构中延续。(设计模式强推) 【不要贪大求全,不要盲目照搬大公司的架构】
第三章 架构设计流程
识别复杂度——有针对性
- 分析业务逻辑的复杂性
- 是否有做高性能高可用的成本
优先解决最主要的复杂度问题。
使用成熟技术——设计备选方案
- 备选方案以3-5个为最佳
- 备选方案差异要比较明显(比如主备方案和集群方案)
- 备选方案的技术不要局限已经熟悉的技术(如果你有一把锤子,那么所有的问题都是钉子)
- 备选方案不用过于详细(关注技术选型,而不是技术细节)
深思熟虑——评估备选方案
- 性能
- 复杂度和开发时间
- 成本
- 扩展
精雕细琢——详细方案设计
Nginx负载均衡策略的算法选择
- 轮询
- 加权轮询
- ip_hash