本文作者:12叔
我们来分析一下可扩展性架构的设计
可扩展架构
软件系统与硬件和建筑系统最大的差异在于软件是可扩展的
软件系统的这种天生和内在的可扩展的特性,既是其魅力所在,又是其难点所在
幸运的是,可扩展性架构的设计方法很多,但万变不离其宗,所有的可扩展性架构设计, 背后的基本思想都可以总结为一个字 : 拆!
拆,就是将原本大一统的系统拆分成多个规模小的部分,扩展时只修改其中一部分即可, 无须整个系统到处都改,通过这种方式来减少改动范围,降低改动风险
拆分思路有如下三种 。
- 面向流程拆分:将整个业务流程拆分为几个阶段,每个阶段作为一部分。
- 面向服务拆分:将系统提供的服务拆分,每个服务作为一部分。
- 面向功能拆分:将系统提供的功能拆分,每个功能作为一部分
不同的拆分方式 , 将得到不同的系统架构,典型的可扩展系统架构如下。
- 面 向流程拆分 : 分层架构。
- 面向服务拆分: SOA 、 微服务。
- 面向功能拆分 : 微内核架构。
这几个系统架构并不是非此即彼的,而是可以在系统架构设计中进行组合使用的
分层架构
分层架构设计最核心的一点就是需要保证各层之间的差异足够清 晰,边界足够明显,让人看到架构图后就能看懂整个架构,这也是分层不能分太多层的原因
分层架构之所以能够较好地支撑系统扩展,本质在于:隔离关注点, 即每个层 中的组件只 会处理本层的逻辑 。 比如说, 展示层只 需要处理展示逻辑,业务层 中只 需 要处理业务逻辑,这样我们在扩展某层时,其他层是不受影响的,通过这种方式可以支撑系统 在某层上快速扩展
当然,并不是简单地分层就一定能够实现隔离关注点从而支撑快速扩展,分层时要保证层 与层之间的依赖是稳定的,才能真正支撑快速扩展
分层结构的这种约束,好处在于强制将分层依赖限定为两两依赖,降低了整体系统复杂度
但分层结构的代价是不管这个业务有多么简单,每层都必须要参与处理,甚至可能每层 都写了一个简单的包装函数
SOA 架构
SOA 提出的背景是企业内部的 IT 系统重复建设且效率低下, 为了应对传统 IT 系统存在的问题, SOA 提出了 三个关键概念
- 服务
- ESB
- 松耦合
SOA 解决了传统 IT 系统重复建设和扩展效率低的问题,但其本身也引入了更多的复杂性 。 SOA 最广为人垢病的就是 ESB, ESB 需要实现与各种系统间的协议转换、数据转换、透明的动 态路由等功能
SOA 的 ESB 设计也是无奈之举。我们回想一下 SOA 的提出背景就可以发现,企业 在应用 SOA 时,各种异构的 IT 系统都已经存在很多年了,完全重写或按照统一标准进行改造 的成本是非常大的,只能通过 ESB 方式去适配已经存在的各种异构系统
微服务
SOA和微服务的关系和区别
- SOA 的服务粒度要粗一些,而微服务的服务粒度要细一些
- SOA 采用了 ESB 作为服务间通信的关键组件,负责服务定义、服务路由 、消息转换、消息传递,总体上是重量级的实现。微服务推荐使用统一的协议和格式
- SOA 对服务的交付并没有特殊要求,因为 SOA 更多考虑 的是兼容己有的系统:微服务 的架构理念要求“快速交付
- SOA 更加适合于庞大、 复杂、异构的企业级系统,微服务更加适合于快速、轻量级、基于 Web 的互联网系统
SOA 和微服务本质上是两种不同的架构设计理念,只是在“服务”这个点上有交集而己
微服务的坑
- 服务划分过细,服务间关系复杂
- 服务数量太多,团队效率急剧下降
- 调用链太长,性能下降
- 调用链太长,问题定位困难
- 没有自动化支撑,无法快速交付
- 没有服务治理,微服务数量多了后管理混乱
服务粒度
针对微服务拆分过细导致的问题,建议基于团队规模进行拆分
最好一个微服务三个人负责开发 。 当我们在实施微服务 架构时,根据团队规模来划分微服务数量,如果业务规继续发展,团队规模扩大,我们再将己 有的微服务进行拆分
从系统规模来讲, 3 个人负责开发一个系统,系统的复杂度刚好达到每个人都能全 面理解整个系统,又能够进行分工的粒度
从团队管理来说, 3 个人可以形成一命稳定的备份,即使 l 个人休假或调配到其他 系统,剩余 2 个人还可以支撑
从技术提升的角度来讲, 3 个人的技术小组既能够形成有效的讨论,又能够快速达 成一致意见
拆分方法
基于业务逻辑拆分
这是最常见的-种拆分方式,将系统中的业务模块按照职责范围识别出来,每个单独的业 务模块拆分为一个独立的服务,具体拆分的时候,首先根据团队规模计算一下大 概的服务数量范围,然后确定合适的“职责范围”,否则就可能出现划分过细的情况
基于可扩展拆分。
将系统中的业务模块按照稳定性进行排序,将己经成熟和改动不大的服务拆分为稳定服务, 将经常变化的服务拆分为变动服务。稳定的服务粒度可以粗一些,即使逻辑上没有强关 联的服务,也可以放在同一个子系统中
这样拆分主要是为了提升项目快速迭代的效率,避免在开发的时候,不小心影响己有的成 熟功能导致线上问题。
基于可靠性拆分
将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核 心服务拆分开来,然后重点保证核心服务的高可用。具体拆分的时候,核心服务可以是一个, 也可以是多个
基于性能拆分
基于性能拆分和基于可靠性拆分类似,将性能要求高或性能压力大的模块拆分出来,避免 性能压力大的服务影响其他服务。常见的拆分方式和具体的性能瓶颈有关,可以拆分 Web 服务、 数据库、缓存等
以上几种拆分方式不是多选 1 ,而是可以根据实际情况自由排列组合
基础设施
大部分人主要关注的是微服务的“ small”和 “ lightweight”特性, 但实际上真正决定微服 务成败的,恰恰是那个被大部分人都忽略的automated
微服务并不是很多人认为的那样又简单又轻量级。要做好微服务,这些基础设施都是必不可少的 , 否则微服务就会变成一个焦油坑,让业务和团队在里面不断挣扎而无法自拔
自动化测试
微服务将原本大一统的系统拆分为多个独立运行的“微”服务,微服务之间的接口数量大 大增加, 并且微服务提倡快速交付,版本周期短 ,版本更新频繁。如果每次更新都靠人工回归 整个系统,则工作量大,效率低下,达不到“快速交付”的目的,因此必须通过自动化测试系 统来完成绝大部分测试回归的工作
自动化部署
相比大一统的系统,微服务需要部署的节点增加了几倍甚至十几倍,微服务部署的频率也 会大幅提升 ( 例如,我们的业务系统 70%的工作日都有部署操作),综合计算下来 , 微服务部署 的次数是大一统系统部署次数的几十倍。这么大量的部署操作,如果继续采用人工手工处理, 需要投入大量的人力,且容易出错,因此需要自动化部署的系统来完成部署操作。
配置中心
微服务的节点数量非常多,通过人工登录每台机器手工修改,效率低,容易出错。特别是 在部署或排障时,需要快速增删改查配置,人工操作的方式显然是不行的。除此以外, 有的运 行期配置需要动态修改并且所有节点即时生效,人工操作是无法做到的 。综合上述的分析,微 服务需要一个统一的配置中 心来管理所有微服务节点的配置
API 网关
系统拆分为微服务后,内部的微服务之间是互联互通的,相互之间的访 问都是点对点 的 。 如果外部系统想调用系统的某个功能,也采取点对点的方式,则外部系统会非常“头大飞因为 在外部系统看来 , 它不需要也没办法理解这么多微服务的职责分工和边界,它只会关注它需要 的能力,而不会关注这个能力应该由哪个微服务提供
综合上述分析,微服务需要一个统一的 API 网关,负责外部系统的访问操作
服务容错
系统拆分为微服务后,单个微服务故障的概率变小,故障影响范围也减少,但是微服务的 节点数量大大增加。从整体上来看,系统中某个微服务出故障的概率会大大增加。前面我们分 析微服务陷阱时提到微服务具有故障扩散的特点,如果不及时处理故障,故障扩散开来就会导 致看起来系统中很多服务节点都故障了。因此需要微服务能够自动应对这种出错场景,及时进 行处理。否则如果节点一故障就需要人工处理,投入人力大,处理速度慢。而一旦处理速度慢, 则故障就很快扩散,所 以我们需要服务容锚的能力。
服务监控
系统拆分为微服务后,节点数量大大增加,导致需要监控的机器、网络、进程、接口调用 数等监控对象的数量大大增加;同时,一旦发生故障,我们需要快速根据各类信息来定位故障 。 这两个目标如果靠人力去完成是不现实的
服务监控的主要作用有几个
- 实时搜集信息并进行分析,避免故障后再来分析,减少了处理时间。
- 服务监控可以在实时分析的基础上进行预瞥,在问题萌芽的阶段发觉并预警,降低了问题影响的范围和时间
服务跟踪
服务监控可以做到微服务节点级的监控和信息收集,但如果我们需要跟踪某一个请求在微 服务中的完整路径,服务监控是难以实现的。
服务监控和服务跟踪的区别可以简单概括为宏观和微观的区别 。 例如, A 服务通过 HTTP 协议请求 B 服务 10 次, B 通过 HTTP 返回 JSON 对象,服务监控会记录请求次数、响应时间平 均值、响应时间最高值、错误码分布这些信息;而服务跟踪会记录其中某次请求的发起时间、 响应时间、响应错误码、请求参数、返回的 JSON 对象等信息。
服务跟踪一般主要用于两个目的
- 采样跟踪
- 染色跟踪
服务安全
系统拆分为微服务后,数据分散在各个微服务节点上。从系统连接的角度来说,任意微服 务都可以访 问所有其他微服务节点 ;但从业务的角度来说,部分敏感数据或操作只能部分微服 务可 以访问,而不是所有的微服务都可以访问。因此需要设计服务安全机制来保证业务和数据 的安全性
服务安全主要分为三部分。
- 接入安全
- 数据安全
- 传输安全
微内核架构
微内核架构,也被称为插件化架构,是一种面向功能进行拆分的可扩展性架构,通常用于实现基于产品
微内核架构包含两类组件 :
核心系统和插件模块。
核心系统负责和具体业务功能无关的通用功能,例如模块加载、模块间通信等:插件模块负责实现 具体的业务逻辑
核心系统功能比较稳定,不会因为业务功能扩展而不断修改,插件模块可以根据业务功能 的需要不断地扩展。微内核架构通过隔离变化到插件的方式提供了灵活性、可扩展性
微内核的核心系统设计的关键技术有几部分
- 插件管理 核心系统需要知道当前有哪些插件可用,如何加载这些插件,什么时候加载插件
- 插件连接 插件连接指插件如何连接到核心系统
- 插件通信 插件通信指插件间的通信
OSGi架构
OSGi 是一个插件化的标准,而不是一个可运行的框架
规则引擎架构
规则引擎从结构上来看也属于微内核架构的一种具体实现,其中执行引擎可以看作微内核, 执行引擎解析配置好的业务流,执行其中的条件和规则,通过这种方式来支持业务的灵活多变
规则引擎在计费、保险、促销等业务领域应用较多。
架构演进
我们可以简单地将企业的业务分为两类: 一类是产品类,另一类是服务类。
对于产品类业务,答案看起来很明显: 技术创新推动业务发展!
对于“服务”类的业务,答案和产品类业务正好相反:业务发展推动技术的发展
对于架构师来说,判断业务当前和接下来一段时间的主要复杂度是什么是非常关键 的 。判断不准确就会导致投入大量的人力和时间做了对业务没有作用的事情
不同时期业务的复杂性的表现
初创期
初创期的业务对技术就一个要求 : “快”,但这个时候却又是创业团队最弱小的时期,可能 就几个技术人员,所以这个时候十八般武艺都需要用上:能买就买 ,有开源的就用开源的
发展期
当业务推出后经过市场验证如果是可行的,则吸引的用户就会越来越多,此时原来不完善 的业务就进入了 一个快速发展的时期 。 业务快速发展时期的主要目 的是将原来不完善的业务逐 渐完善,因此会有越来越多的新功能不断地加入系统中 。 对于绝大部分技术团队来说,这个阶 段技术的核心工作是快速地实现各种需求 , 只有这样才能满足业务发展的需要。
如何做到“快”, 一般会经历如下几个阶段 。
- 堆功能
业务进入快速发展期的初期,此时团队规模也不大,业务需求又很紧,最快实现业务需 求的方式是继续在原有的系统里面不断地增加新的功能, 重构、优化、架构等方面的工 作即使想做 , 也会受制于人力和业务发展的压力而放在一边
- 优化
“堆功能”的方式在刚开始的时候好用,因为系统还比较简单,但随着功能越来越多 , 系统开始变得越来越复杂,后面继续堆功能会感到越来越吃力 , 速度越来越慢。一种典 型的场景是做一个需求要改好多地方, 一不小心就改出了问题。直到有一天,技术团队 或产品人员再也受不了这种慢速的方式, 终于下定决心要解决这个问题
架构期
经过优化期后 ,如果业务能够继续发展,慢慢就会发现优化也顶不住了,毕竟再怎么优化, 系统的能力总是有极限的
架构期可以用的手段很多,但归根结底可以总结为一个字 “拆
- 拆功能:例如,将购物系统拆分为登录认证子系统、订单系统 、 查询系统、分析系统等。
- 拆数据库: MySQL 一台变两 台, 2 台变 4 台,增加 DBProxy 、 分库分表等。
- 拆服务器:服务器一台变两台 , 2 台变 4 台,增加负载均衡的系统
竞争期
当业务继续发展 ,已经形成一定规模后 , 一定会有竞争对手开始加入行业来竞争,毕竟谁 都想分一块蛋糕,甚至有可能一不小心还会成为下一个 BAT。当竞争对手加入后,大家互相学 习和模仿,业务更加完善,也不断有新的业务创新出来,而且由于竞争的压力,对技术的要求 是更上一层楼的“快”了。
原来系统数量越来越多,到了一个临界点后就产生了质变,即系统数量的量变带来了技术 工作的质变。主要体现在如下几个方面
- 重复造轮子
- 系统交互一团乱麻
针对这个时期业务变化带来的问题,技术工作主要的解决手段如下 。
- 平台化
- 服务化
成熟期
当企业熬过竞争期,成为行业的领头羊,或者整个行业整体上已经处于比较成熟的阶段, 市场地位己经比较牢固后,业务创新的机会己经不大
此时技术上其实也基本进入了成熟期,该拆的也拆了,该平台化的也平台化了,技术上能 做的大动作其实也不多了,更多的是进行优化。但有时候也会为了满足某个优化,系统做很大 的改变
用户规模
互联网业务的发展第二个主要方向就是“用户量越来越大”。互联网业务的发展会经历“初 创期、发展期、竞争期、成熟期”几个阶段,不同阶段典型的差别就是用户量的差别,用户量 随着业务的发展而越来越大
用户量增大对技术的影响主要体现在两个方面:性能要求越来越高、可用性要求越来越高
性能 用户量增大给技术带来的第 一个挑战就是性能要求越来越高
可用性 用户量增大对技术带来的第二个挑战就是可用性要求越来越高
架构重构
少部分架构演化可能需要推倒重来进行重写,但绝大部分的架构演化都是通过架构重构来实现的。相比 全新的架构设计来说,架构重构对架构师的要求更高
- 业务己经上线,不能停下来
- 关联方众多, 牵一发动全身
- 旧架构的约束
即使是我们决定推倒重来,完全抛弃旧的架构,设计新的架构,新架构也会受到旧架构的 约束和影响,因为业务在旧架构上产生的数据是不能推倒重来的,新架构必须考虑如何将旧架 构产生的数据转换过来
期望通过架构重构来解决所有问题当然是不现实的,所以架构师的首要任务是从一大堆纷 繁复杂的问题中识别出真正要通过架构重构来解决的问题,集中力量快速解决,而不是想着通 过架构重构来解决所有的问题
总结一下重构的做法,其实就是“分段实施”,将要解决的问题根据优先级、重要性、实施 难度等划分为不同的阶段,每个阶段聚焦于一个整体的目标,集中精力和资源解决一类问题。 这样做有几个好处
- 每个阶段都有明确目标,做完之后效果明显,团队信心足,后续推进更加容易。
- 每个阶段的工作量不会太大,可以和业务并行。
- 每个阶段的改动不会太大,降低了总体风险。
具体如何制定“分段实施”的策略呢
- 划分优先级
- 问题分类
- 先易后难
参考资料
<亿级流量网站架构核心技术> <从零开始学架构> <大型网站技术架构>
架构系列合辑
本文转自:https://my.oschina.net/jayqqaa12/blog/3161734
© 著作权归作者所有