从零开始学架构-笔记

发布于:2024-05-11 ⋅ 阅读:(16) ⋅ 点赞:(0)

欢迎大家关注  ,希望对大家有所帮助,要是觉得可以的话麻烦给点一下Star哈

前言

每一个程序员都有一个架构师的梦,可理想很丰满,现实很骨感—大部程序员工作中都做着CRUD,但进取心与持续学习的心态还是要有的。掌握架构设计的相关理论是成为架构师的前提。在看了一本《从零开始学架构》后,发现架构设计是有套路的。

image.png 这本书主要阐述了架构学习的方法论:

  1. 清楚地理解架构设计相关的概念、本质、目的,避免架构师在实践过程中把握不住重点、分不清主次,眉毛胡子一把抓,导致架构设计变形或者“四不像” 。
  2. 掌握通用的架构设计原则,无论是何种业务或技术,架构师在判断和选择的时候有一套方法论可以参考,避免架构设计举棋不定,或者拍脑袋式设计。
  3. 掌握标准的架构设计流程,即使是刚开始做架构设计的新手,也能够按照步骤一步一步设计出合适的架构,避免某些步骤缺失导致错误的架构设计。
  4. 深入理解已有的架构模式,做到能够根据架构特点快速挑选合适的模式完成架构设计,或者在已有的模式上进行创新,或者将已有的模式组合出新的架构;

1. 概念和基础

1.1 架构基础

1.1 什么是架构

架构就是软件系统的结构,是顶层设计,它明确软件系统包括哪些个体:子系统、模块和组件等;同时明确了个体运作和个体之间协作的规则。框架是面向编程或配置的半成品;组件是从技术维度上的复用;模块是从业务维度上职责的划分;系统是相互协同可运行的实体。

image.png

1.1.2 架构设计的目的

做任何事情只有明确了目的,才能把握方向,从而制定方案并执行,架构设计也不例外。架构设计的主要目的是为了解决软件系统复杂度带来的问题。小到管理系统大到淘宝、微信,在设计开发过程中,都需要进行架构设计。而由于软件系统之间的复杂度不同,架构设计难度也不一样,但基本流程都相似,掌握了架构设计的流程,即使简单的对内的工具平台也能玩出花儿来。

1.1.3 软件复杂度的来源

既然架构设计的主要目的是为了解决软件系统复杂度带来的问题,那么软件的复杂度主要是由什么引起的呢,明确了复杂度的来源,也就明确了架构设计要解决的问题。

image.png

复杂度主要包括高性能、高可用、易扩展、可伸缩、安全性和低成本六个来源,这六个问题覆盖了应用系统要解决的大部分问题。

1.2 架构设计原则

1.2.1 合适原则

合适的架构优于业界领先的架构。真正优秀的架构都是在企业当前人力、条件、业务等各种约束下设计出来的,能够合理地将资源整合在一起并发挥出最大功效,并且能够快速落地 。

1.2.2 简单原则

简单的架构优于复杂的架构。软件领域的复杂性体现在两方面:结构的复杂性、逻辑的复杂性。

1.2.3 演化原则

架构需要随着业务的发展而不断演化。对于建筑来说,永恒是主题:而对于软件来说,变化才是主题。软件架构设计类似于生物演化。

1.3 设计流程

image.png 重点说一下识别复杂度与设计备选方案这两个过程。

1. 识别复杂度

架构的复杂度来源虽然有六个,但主要复杂度来自于高性能、高可用和易扩展。在讨论架构设计的时候我们更多的是讨论这三点,但架构并不一定任何时候都必须满足这三个需求。根据软件系统的不同,大部分情况下只需要满足其中的一个到两个,很少能用到三个。

2. 设计备选方案

解决高性能、高可用和易扩展三个复杂度来源的成熟的技术方案有很多。比如:针对高性能的缓存、负载均衡、多路复用方案;针对高可用的主备、集群、异地多活方案;提升软件扩展性的设计模式、架构分层、插件化等方案。在明确了软件系统的复杂度主因(大部分情况下,核心复杂度只有1到2个)以后就可以按图索骥的找到备选解决方案。

3. 备选方案360度环评

image.png

架构师需要对技术的细节和原理有较深入的理解 , 避免成为 PPT架构师。通过分步骤、分阶段 、 分系统等方式,尽量降低方案复杂度 。采取设计团队的方式来进行设计,可以博采众长,汇集团队经验,减少思维和经验盲区

2. 高性能架构模式

高性能是架构设计复杂度来源之一,任何软件系统对高性能都有所要求,只是要求的标准不一样。对性能要求越高的软件系统架构设计越复杂,反之越容易。

高性能架构主要包括存储高性能与计算(服务)高性能两个方面

2.1 存储高性能

对存储系统进行高性能设计的方法如下图所示。

image.png

  • 关系数据库的高性能设计,主要的做法是读写分离、分库分表

  • 高性能NoSQL(Not only SQL),NoSQL不应该是关系型数据库的替代者,而应该是作为补充者,因为NoSQL其实是牺牲了ACID中某一个甚至某几个特性来适应大数据场景下的性能要求,在某些高保障场景下(如金融领域)其实是不适用的;

  • 缓存,主要也是为了解决的关系行数据库中无能为力解决的问题,解决思路是,将数据取出来之后放到缓存服务器,减少对关系型数据库的访问,缓存需要的注意的点是缓存穿透、缓存雪崩、缓存热点等问题;

2.2 计算高性能

高性能架构设计主要集中在两方面:尽量提升单服务器的性能,将单服务器的性能发挥到极致。如果单服务器无法支撑性能,设计服务器集群方案。除了这两点,最终系统能否实现高性能,还和具体的实现及编码相关。但架构设计是高性能的基础,如果架构设计没有做到高性能,则后面的具体实现和编码能提升的空间是有限的。形象地说,架构设计决定了系统性能的上限,实现细节决定了系统性能的下限

计算(服务)高性能包括单机与集群两个方向,这两个方向的高性能方案分别如下图所示。

image.png

2.2.1 单服务器高性能

单服务器实现高性能的关键之一就是服务器采取的并发模型,并发模型有两个关键设计点:

  • 服务器如何管理连接
  • 服务器如何处理请求

两个设计点最终都和操作系统的I/O模型及进程模型相关。

  • I/O 模型:阻塞、非阻塞、同步、异步
  • 进程模型:单进程、多进程、多线程

PPC和TPC模式的优点是实现简单,缺点是都无法支撑高并发的场景,尤其是互联网发展到现在,各种海量用户业务的出现,PPC和TPC完全无能为力。ReactorProactor模式是更好的应对高并发场景的单服务器模式。

详细可参考:

2.2.2 集群高性能

集群实现高性能的复杂性主要体现在需要增加一个任务分配器(负载均衡器),以及为任务选择一个合适的任务分配算法。负载均衡系统包括 3 种:DNS 负载均衡、硬件负载均衡和软件负载均衡算法

DNS 负载均衡用于实现地理级别的负载均衡;硬件负载均衡用于实现集群级别的负载均衡;软件负载均衡用于实现机器级别的负载均衡。

image.png

整个系统的负载均衡分为三层:

  1. 地理级别负载均衡 : 部署在北京、广州、上海三个机房,当用户访问时,DNS 会根据用户的地理位置来决定返回哪个机房的 IP ,图中返回 了广州机房的 IP 地址,这样用户就访问到广州机房了。
  2. 集群级别负载均衡:广州机房的负载均衡用的是 FS 设备, FS 收到用户请求后,进行集群级别的负载均衡,将用户请求发给 3 个本地集群中的一个,我们假设 FS 将用户请求发给了“广州集群 2 ”。
  3. 机器级别的负载均衡:广州集群 2 的负载均衡用的是 Nginx, Nginx 收到用户请求后,将用户请求发送给集群里面的某台服务器,服务器处理用户的业务请求井返回业务响应。

3. 高可用架构模式

3.1 数据高可用

数据高可用分两部分,一是数据一致性,二是数据备份

3.1.1 数据一致性(CAP+BASE+2PC+3PC)

image.png

BASE理论本质上是对CAP的延伸和补充,更具体地说,是对CAP中AP方案的一个补充。现实的分布式系统中,想实现完美的CAP根本不可能,也不需要这么严格的CAP,BASE几乎适用于所有场景,对于一些对数据一致性要求达到100%的场景(如金融领域),可以选择CA,也就是单机。

刚性事务(如单机数据库事务)完全遵循ACID规范。柔性事务(如分布式事务)为了满足可用性、性能与降级服务的需要,降低一致性(Consistency)与隔离性(Isolation)的要求,遵循 BASE理论,传统的ACID事务对隔离性的要求非常高,在事务执行过程中,必须将所有的资源对象锁定,因此对并发事务的执行极度不友好,柔性事务(比如分布式事务)的理念则是将锁资源对象操作从本地资源对象层面上移至业务逻辑层面,再通过放宽对强一致性要求,以换取系统吞吐量的提升。

image.png

参考

3.1.2 存储高可用(数据备份)

存储高可用方案的本质都是通过将数据复制到多个存储设备,通过数据冗余的方式来实现高可用,其复杂性主要体现在如何应对复制延迟和中断导致的数据不一致问题。解决方案大致分成双机架构和集群架构,但这两者并不是互斥的,可以相互包含,例如OceanBase作为分布式关系型数据库,总体上采用的是数据分散集群,单一数据库节点又采用了一主多从冗余的架构。

在CAP理论提出十二年之后,其作者又出来辟谣。“三选二”的公式一直存在着误导性,它会过分简单化各性质之间的相互关系。首先,由于分区很少发生,那么在系统不存在分区的情况下没什么理由牺牲C或A。其次,C与A之间的取舍可以在同一系统内以非常细小的粒度反复发生,而每一次的决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同。最后,这三种性质都可以在程度上衡量,并不是非黑即白的有或无。可用性显然是在0%到100%之间连续变化的,一致性分很多级别,连分区也可以细分为不同含义,如系统内的不同部分对于是否存在分区可以有不一样的认知。所以一致性和可用性并不是水火不容,非此即彼的。Paxos、Raft等分布式一致性算法就是在一致性和可用性之间做到了很好的平衡的见证

image.png OceanBase的redolog是使用分布式一致性算法Paxos实现的,每一笔事务,主库执行完成后,要同步到半数以上库(包括主库自身),例如3个库中的2个库,或者5个库中的3个库,事务才成功,这样少数库异常后业务并不受影响。所以在CAP理论中,虽然OceanBase使用的是强一致模型,但是OceanBase能在一定网络分区的情况下做到极高的可用性(通俗点讲就是多于半数的机器还活着的时候就能干活),虽然选择了C与P,但A也能做到5个9。

3.2 计算高可用

计算高可用的主要设计目标是当出现部分硬件损坏时,计算任务能够继续正常运行。因此计算高可用的本质是通过冗余来规避部分故障的风险

  • 主备
    • 热备,冷备,温备
  • 主从
  • 对称集群(负载均衡集群)
  • 非对称集群

3.3 业务高可用

业务及服务高可用的设计方法如下图所示: image.png

业务高可用的一般做法是做异地多活,难点是异地模式会因为物理延迟产生数据不一致问题,常见的模式有:同城异地、跨城异地和跨国异地。

接口服务高可用方案主要有以下4种:

  • 降级:将业务或者接口功能降低,只提供部分功能或者完全停掉所有功能。常见实现降级方式有系统后门降级和独立系统降级。
  • 限流:降级是故障后的事后处理,而限流是故障前的预防。限流是指只允许能够承受的访问量进来,超出系统系统-访问能力的将被放弃。常用的限流方式可以分为分类基于请求限流和基于资源限流。
  • 排队:是流量限制的一个变种,限流是直接拒绝用户,排队是让用户等待一段时间。
  • 服务熔断:熔断与降级概念非常容易混淆,降级是为了应对服务自身的故障熔断的目的是为了应对外部系统故障的情况:主动断开依赖的其他外部的不可用服务,防止造成更多的雪崩效应。

4. 可扩展架构模式

这个世界唯一不变的是变,与建筑架构不同,软件系统架构是一个不断演变的过程。如果软件系统从一开始没做好软件架构,遇到每次大的改变都需要重构,将是不能接受的。

可扩展性架构设计方式有很多,但万变不离其宗,所有的可扩展架构的背后基本思想都可以总结为一个字:“拆”。可以面向流程拆分,面向服务拆分,面向功能拆分(这三种拆分方式其实也不是互斥的,而可以相互借用)。

image.png

其中可扩展架构大致分成三种类型:分层架构与SOA、微服务、微内核

4.1 传统的可扩展架构模式——分层与SOA

image.png

无论采取何种分层维度,分层架构设计最核心的一点就是需要保证各层之间的差异足够清晰,边界足够明显,让人看到架构图后就能看懂整个架构,这也是分层不能分太多层的原因。否则如果两个层的差异不明显,就会出现程序员小明认为某个功能应该放在A层,而程序员老王却认为同样的功能应该放在B层,这样会导致分层混乱。

分层架构之所以能够较好地支撑系统扩展,本质在于隔离关注点,即每个层中的组件只会处理本层的逻辑。分层结构的另外一个特点就是层层传递,也就是说一旦分层确定,整个业务流程是按照层进行依次传递的,不能在层之间进行跳跃。最简单的C/S结构,用户必须先使用C 层,然后C层再传递到S层,用户是不能直接访问S层的。

4.2 微服务

image.png

微服务与SOA都是关注服务,但是这两者服务粒度不同,架构设计也不同,SOA是为了兼容企业中存在很久的系统,而微服务是为了适应互联网系统开发。微服务需要配套的基础设施支持,这些基础设施包括自动化测试、自动化部署、配置中心、服务发现、服务路由、监控、容错、服务安全等,只有把这些基础设施都做好了才能很好的实践微服务。

image.png

微服务需要避免踩的陷阱,简单提炼为:

  • 微服务拆分过细,过分强调“small”,造成服务数量众多,复杂度反而上升
  • 微服务基础设施不健全,忽略了“automated”
  • 微服务并不轻量级,规模大了后,“lightweight”不再适应

4.3 微内核——插件化架构

image.png

微内核是一种插件化架构,关键点是插件管理、插件连接、插件通信,常见的微内核结构:OGSI架构、规则引擎架构,微内核架构基本示意图如下。

image.png

上图中核心系统Core System功能比较稳定,不会因为业务功能扩展而不断修改,插件模块可以根据业务功能的需要不断地扩展。微内核的架构本质就是将变化部分封装在插件里面,从而达到快速灵活扩展的目的,而又不影响整体系统的稳定。微内核的核心系统设计的关键技术有:插件管理、插件连接和插件通信。常见的插件连接机制有OSGi(Eclipse 使用)、消息模式、依赖注入(Spring使用),甚至使用分布式的协议都是可以的,比如RPC或者HTTP Web的方式。

最受欢迎的开源关系型数据库MySQL就是采用插件化架构,最典型的就是存储引擎模块,插件式架构使存储引擎的加载、卸载与server层解耦。

最典型的实现就是 Dubbo, 有兴趣的同学可以参见:

5. 架构实战

5.1 架构重构

有的方式

架构师的首要任务是从一大堆纷繁复杂的问题中识别出真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通过架构重构来解决所有的问题

合纵连横

  • 合纵:
    • 架构重构是大动作,持续时间比较长,而且会占用一定的研发资源,包括开发和测试,因此不可避免地会影响业务功能的开发。因此,要想真正推动一个架构重构项目启动 ,需要花费大量的精力进行游说和沟通。
    • 在沟通协调时,将技术语言转换为通俗语言,以事实说话,以数据说话,是沟通的关键 !
  • 连横:
    • 除了以上讨论的和上下游沟通协调,有的重构还需要和其他相关或配合的系统的沟通协调
    • 效的策略是“换位思考、合作双赢、关注长期飞简单来说就是站在对方的角度思考,重构对他有什么好处,能够帮他解决什么问题,带来什么收益。
    • 除了计划灵活一点,方案也可以灵活一点 : 我们可以先不做这个系统相关的重构,先把其他需要重构的做完。因为大部分需要重构的系统,需要做的事情很多,分阶段处理,在风险规避、计划安排等方面更加灵活可控

运筹帷幄

image.png

真正的架构重构在第三阶段,第一阶段和第二阶段都是为了第三阶段做准备而己,但如果没有第一阶段和第二阶段的铺垫, 直接开始第三阶段的架构重构工作,架构重构方案需要耦合第一阶段和第二阶段的一些事项(例如,业务降级、接入服务中心等〉,会导致架构重构方案不聚焦,而且异常复杂。主要还是为了集中有限的资源,某个阶段集中解决某一类问题

  • 划分优先级
  • 问题分类
  • 先易后难

项目管理+技术能力(文武双全)

真正的架构师,当然必须具备一定的项目经理技能,但更重要的还是技术能力,道理很简单 : 再好的饼,最后实现不了,都是空谈!“项目管理能力”是“文”的能力,“技术能力”是“武”的能力,架构师必须文武双全,才能最终解决 问题!

5.2 开源系统

选,如何选择一个开源项目

  • 聚焦是否满足当前业务
  • 聚焦是否成熟
  • 聚焦运维能力

用,如何使用开源方案

  • 深入研究,仔细测试
  • 小心应用,灰度发布
  • 做好应急,以防万一

改,如何基于开源项目二次开发

  • 保持纯洁,加以包装
  • 发明你要的轮子

参考文档

从零开始学架构-照着做,你也能成为架构师


网站公告

今日签到

点亮在社区的每一天
去签到