此系列文章为极客时间上从0开始学架构学习后感悟总结,虽然隔了一段时间了,那么就再看一遍并且进行感悟升华,排版格式上有问题,后期再复习时也会进行更新
架构设计的关键思维是判断和取舍,程序设计的关键思维是逻辑和实现。
架构设计的主要目的是为了解决软件系统复杂度带来的问题,架构师该做的有的放矢,而不是贪大求全
一.架构复杂度来源---高性能
为了满足业务的所需性能,单机早已无法应当,因此都是采用集群方式来应对,使用集群方式后就会变得更复杂。
很简单的方式,我们加入新机器后便需要再加入任务分配器,从单机就进化成了下图,很好理解
随着为了满足业务性能要求增加了新服务器后,引出了一些问题
- 多了一个任务分配器,它可能是硬件(F5),也更有可能是负载均衡软件(lvs/nginx/haproxy),也可能是自研系统
- 任务分配器内有算法,使用不同的算法会对我们的性能有不同的改善,不同的业务场景有各自所需的算法
- 任务分配器与后端业务机器之间的联通问题
- 一台机器可以承受5000业务量(假定),但是2台并不是1W,实际需要打个8折,即8000,如果业务还比较复杂,那么可能只有5000,我们的收益会越来越低
- 随着业务量的增加,单台任务分配器都会成为瓶颈,即连任务分配器我们也需要变成集群模式,任务分配器前面也需要选择对应的分配策略(即任务分配器的任务分配器),常用的有DNS 轮询、智能DNS、CDN、GSLB 设备
- 在任务分配器变成多台的情况下,我们的架构从原本的一对多变成了多对多
7.随着任务分配器与业务服务器的数量增加,我们的故障率,管理成本都在提升
业务拆分,将大的业务拆分成小业务,将系统变得更简单
- 简单的系统更加容易做到高性能,系统简单了那么影响性能的点就少了,也更加容易进行针对性优化
- 可以针对单个任务进行扩展,在业务被拆分后我们就可以针对各小业务进行对应扩展,而不是牵扯到整个大业务
业务拆分不是银弹,无法通过无限的拆分来解决因为业务性能带来的复杂性问题,无限的拆分反而会影响到业务原本的性能
由于不合理的拆分,原本的一次请求变成了多次,那么在网络上的传输将会越来越多,反而影响到性能
二. 架构复杂度来源---高可用
系统无中断地执行其功能的能力,代表系统的可用性程度,是进行系统设计时的准则之一。系统的高可用方案五花八门,但万变不离其宗,本质上都是冗余(你这个问题充钱就能解决)。
好了我们充钱后又带来了一些问题,这些问题貌似通过充更多的钱还解决不了
- 计算高可用,我们需要保证无论在哪台机器上进行计算,同样的算法和输入数据,产出的结果都是一样的,如下图我们的任务分配的时候可选择的算法有主备、主主,主备方案又可以细分为冷备、温备、热备
2.存储高可用,存储高可用的难点不在于如何备份数据,而在于如何减少或者规避数据不一致对业务造成的影响
三. 架构复杂度来源---扩展性
可扩展性指系统为了应对将来需求变化而提供的一种扩展能力,当有新的需求出现时,系统不需要或者仅需要少量修改就可以支持,无须整个系统重构或者重建。
- 预测变化,软件系统与硬件或者建筑相比,有一个很大的差异:软件系统在发布后还可以不断地修改和演进,这就意味着不断有新的需求需要实现,它的难点在于
*不能每个设计点都考虑可扩展性。
*不能完全不考虑可扩展性。
*所有的预测都存在出错的可能性。
2. 应对变化,既然我们预测变化了,那么就要做出相对应的策略。
第一种策略是将“变化”封装在一个“变化层”,将不变的部分封装在一个独立的“稳定层”
*系统需要拆分出变化层和稳定层
*需要设计变化层和稳定层之间的接口
第二种策略是提炼出一个“抽象层”和一个“实现层”,抽象层是稳定的,实现层可以根据具体业务需要定制开发,当加入新的功能时,只需要增加新的实现,无须修改抽象层
四. 架构复杂度来源---低成本、安全、规模
1.往往只有“创新”才能达到低成本目标。无论是引入新技术,还是自己创造新技术,都是一件复杂的事情。引入新技术的主要复杂度在于需要去熟悉新技术,并且将新技术与已有技术结合起来;创造新技术的主要复杂度在于需要自己去创造全新的理念和技术,并且新技术跟旧技术相比,需要有质的飞跃。
2.功能安全与架构安全。我们需要在代码框架层面与物理层面都做出改变。但是因为改变我们的架构需要一直进化变化,造成困难
3. 规模带来复杂度的主要原因就是“量变引起质变”
*功能越来越多,导致系统复杂度指数级上升
*数据越来越多,系统复杂度发生质变
架构设计的 3 个原则
一. 合适原则
合适原则宣言:“合适优于业界领先”。
- 没那么多人,却想干那么多活,是失败的第一个主要原因。
- 没有那么多积累,却想一步登天,是失败的第二个主要原因。
- 没有那么卓越的业务场景,却幻想灵光一闪成为天才,是失败的第三个主要原因。
二. 简单原则
简单原则宣言:“简单优于复杂”。
- 结构的复杂性
*组件越多,就越有可能其中某个组件出现故障
*某个组件改动,会影响关联的所有组件
*定位一个复杂系统中的问题总是比简单系统更加困难
2. 逻辑的复杂性
*逻辑复杂几乎会导致软件工程的每个环节都有问题
*复杂算法导致的问题主要是难以理解,进而导致难以实现、难以修改,并且出了问题难以快速解决
三. 演化原则
演化原则宣言:“演化优于一步到位”。
对于建筑来说,永恒是主题;而对于软件来说,变化才是主题
软件架构设计其实更加类似于大自然“设计”一个生物,通过演化让生物适应环境,逐步变得更加强大
架构设计第 1 步:识别复杂度
架构设计的本质目的是为了解决软件系统的复杂性,所以在我们设计架构时,首先就要分析系统的复杂性。只有正确分析出了系统的复杂性,后续的架构设计方案才不会偏离方向;否则,如果对系统的复杂性判断错误,即使后续的架构设计方案再完美再先进,都是南辕北辙,做的越好,错的越多、越离谱。
架构的复杂度主要来源于“高性能”“高可用”“可扩展”等几个方面,但架构师在具体判断复杂性的时候,不能生搬硬套,认为任何时候架构都必须同时满足这三方面的要求。实际上大部分场景下,复杂度只是其中的某一个,少数情况下包含其中两个,如果真的出现同时需要解决三个或者三个以上的复杂度,要么说明这个系统之前设计的有问题,要么可能就是架构师的判断出现了失误,即使真的认为要同时满足这三方面的要求,也必须要进行优先级排序,此时将主要的复杂度问题列出来,然后根据业务、技术、团队等综合情况进行排序,优先解决当前面临的最主要的复杂度问题。
如果出现了需要推倒重来,这个新的方案也必须能够同时解决已经被解决的复杂度问题,一般来说能够达到这种理想状态的方案基本都是依靠新技术的引入。
架构设计第 2 步:设计备选方案
备选方案的数量以 3 ~ 5 个为最佳
备选方案的差异要比较明显
备选方案的技术不要只局限于已经熟悉的技术。常见的错误:备选方案过于详细。
架构设计第 3 步:评估和选择备选方案
列出我们需要关注的质量属性点,然后分别从这些质量属性的维度去评估每个方案,再综合挑选适合当时情况的最优方案。
架构设计第 4 步:详细方案设计
详细设计方案阶段可能遇到的一种极端情况就是在详细设计阶段发现备选方案不可行,一般情况下主要的原因是备选方案设计时遗漏了某个关键技术点或者关键的质量属性。
1.架构师不但要进行备选方案设计和选型,还需要对备选方案的关键细节有较深入的理解。
2. 通过分步骤、分阶段、分系统等方式,尽量降低方案复杂度