可拓展架构模式

1.可扩展架构的基本思想

    拆。就是将原本大一统的系统拆分成多个规模小的部分,扩展时只修改其中一部分即可,无须整个系统到处都改。

1.1 3种拆分思路

    日常生活中的『拆』是破坏性的,而软件系统的『拆』是建设性的。

    • 面向流程拆分:将整个业务流程拆分为几个阶段,每个阶段作为一部分

    • 面向服务拆分:将系统提供的服务拆分,每个服务作为一部分

    • 面向功能拆分:将系统提供的功能拆分,每个功能作为一部分

    • 范围从大到小,流程大于服务,服务大于功能

1.2 可扩展方式

    • 不同的拆分方式,本质上决定了系统的扩展方式

    • 合理拆分可以实现在架构上强制保证在程序出错时,范围不会太广,影响不会太大

1.2.1 面向流程拆分的优势

    扩展时大部分情况只需要修改某一层,少部分情况可能修改关联的两层,不会出现所有层都同时要修改

1.2.2 面向服务拆分的优势

    对某个服务扩展,或者要增加新的服务时,只需要扩展相关服务即可,无须修改所有的服务

1.2.3 面向功能拆分的优势

    对某个功能扩展,或者要增加新的功能时,只需要扩展相关功能即可,无须修改所有的功能模块

1.3 典型可扩展系统架构

    • 面向流程拆分:分层架构

    • 面向服务拆分:SOA、微服务

    • 面向功能拆分:微内核架构

1.4 总结

    • 拆,是核心思想

    • 面向流程拆分里的流程不是业务流程,而是数据流程

    • 服务是一组相似功能的集合,一个功能也可以做成独立的服务

    • 每个服务是独立的子系统,有各自独立的数据库,缓存,服务器

    • 架构设计时可以组合使用不同的拆分方式

 

2.分层架构和SOA

2.1 分层架构

    它也叫分层架构,通常情况下,N至少是2层。例如,C/S架构、B/S架架构、MVC、MVP、操作系统内核架构

2.1.1 C/S架构、B/S架构

    划分的对象是整个系统,划分的维度是用户交互,即将和用户交互的部分独立为一层,支撑用户交互的后台作为另外一层。

2.1.2 MVC架构、MVP架构

    划分的对象是单个业务子系统,划分的维度是职责,将不同的职责划分到独立层,但各层的依赖关系比较灵活

2.1.3 逻辑分层架构

    • 划分的对象可以是单个业务子系统,也可以是整个业务系统,划分的维度也职责

    • 逻辑分层架构中的层是自顶向下依赖的

    • 典型的有操作系统内核架构、TCP/IP架构

    • 下面是Android操作系统架构图

    • 下面是典型的J2EE系统架构图

    • 下面是针对整个业务系统进行逻辑分层的架构图

2.1.4 分层架构设计核心

    • 保证各层之间的差异足够清晰,边界足够明显,让人看到架构图后就能看懂整个架构

    • 较好地支撑系统扩展,本质在于隔离关注点,即每个层中的组件只会处理本层的逻辑

    • 例如,Linux内核为了支撑不同的文件系统格式,抽象了VFS文件系统接口

2.1.5 优势

    分层架构的优势就体现在通过分层强制约束两两依赖,一旦自由选择绕过分层,时间一长,架构就会变得混乱

2.1.6 缺点

    性能,因为每一次业务请求都需要穿越所有的架构分层

2.2 SOA

    Service Oriented Architecture,面向服务架构

2.2.1 背景

    企业各部门有独立的IT系统,比如人力资源系统、财务系统、销售系统,这些系统可能都涉及人员管理,各IT系统都需要重复开发人员管理的功能。例如,某个员工离职后,需要分别到上述三个系统中删除员工的权限

    各个独立的IT系统可能采购于不同的供应商,实现技术不同,企业自己也不太可能基于这些系统进行重构

    随着业务的发展,复杂度越来越高,更多的流程和业务需要多个IT系统合作完成。由于各个独立的IT系统没有标准的实现方式(例如,人力资源系统用Java开发,对外提供RPC;财务系统用C#开发,对外提供SOAP协议),每次开发新的 流程和业务,都需要协调大量的IT系统,同时定制开发,效率很低。

2.2.2 SOA提出的3个关键概念

    • 服务:所有的业务功能都是一项服务,服务就意味着要对外提供开放的能力,当其他系统需要使用这项功能时,无须定制化开发,服务可大可小,可简单也可复杂

    • ESB

    Enterprise Service Bus,企业服务总线

    ESB将企业中各个不同的服务连接在一起

    SOA使用ESB来屏蔽异构系统对外提供各种不同的接口方式,以此达到服务间高校的互联互通

2.2.3 松耦合

    目的是减少各个服务间的依赖和互相影响

    典型的SOA架构如下:

可拓展架构模式_第1张图片

2.2.4 理念

    SOA架构是比较高层级的架构设计理念,一般情况下说企业采用了SOA的架构来构建IT系统,但不会说某个独立的系统采用了SOA的架构。

    例如,某企业采用SOA架构,将系统分为“人力资源管理服务”“考勤服务”“财务服务”,但人力资源管理服务本身通常不会再按照SOA的架构拆分更多服务,也 不会再使用独立的一套ESB,因为这些系统本身可能就是采购的,ESB本身也是采购的,如果人力资源系统本身重构为多个子服务,再部署独立的ESB系统,成本也很高,也没什么收益。

 

3.深入理解微服务架构

    SOA是把多个系统整合,而微服务是把单个系统拆开来,方向正好相反。

 

4.微服务架构最佳实践 - 方法篇

4.1 服务粒度

    针对微服务拆分过细导致的问题,我建议基于团队规模进行拆分,类似贝索斯在定义团队规模时提出的“两个披萨”理论(每个团队的人数不能多到两张披萨都不够吃的地步),分享一个我认为微服务拆分粒度的“三个火枪手”原则,即一个微服务三个人负责开发。当我们在实施微服务架构时,根据团队规模来划分微服务数量,如果业务规继续发展,团队规模扩大,我们再将已有的微服务进行拆分。例如,团队最初有6个人,那么可以划分为2个微服务,随着业务的发展,业务功能越来越多,逻辑越来越复杂,团队扩展到12个人,那么我们可以将已有的2个微服务进行拆分,变成4个微服务。

    为什么是3个人,不是4个,也不是2个呢?

    首先,从系统规模来讲,3个人负责开发一个系统,系统的复杂度刚好达到每个人都能全面理解整个系统,又能够进行分工的粒度;如果是2个人开发一个系统,系统的复杂度不够,开发人员可能觉得无法体现自己的技术实力;如果是4个甚至更多人开发一个系统,系统复杂度又会无法让开发人员对系统的细节都了解很深。

    其次,从团队管理来说,3个人可以形成一个稳定的备份,即使1个人休假或者调配到其他系统,剩余2个人还可以支撑;如果是2个人,抽调1个后剩余的1个人压力很大;如果是1个人,这就是单点了,团队没有备份,某些情况下是很危险的,假如这个人休假了,系统出问题了怎么办?

    最后,从技术提升的角度来讲,3个人的技术小组既能够形成有效的讨论,又能够快速达成一致意见;如果是2个人,可能会出现互相坚持自己的意见,或者2个人经验都不足导致设计缺陷;如果是1个人,由于没有人跟他进行技术讨论,很可能陷入思维盲区导致重大问题;如果是4个人或者更多,可能有的参与的人员并没有认真参与,只是完成任务而已。

    “三个火枪手”的原则主要应用于微服务设计和开发阶段,如果微服务经过一段时间发展后已经比较稳定,处于维护期了,无须太多的开发,那么平均1个人维护1个微服务甚至几个微服务都可以。当然考虑到人员备份问题,每个微服务最好都安排2个人维护,每个人都可以维护多个微服务。

4.2 拆分方法

    基于“三个火枪手”的理论,我们可以计算出拆分后合适的服务数量,但具体怎么拆也是有技巧的,并不是快刀砍乱麻随便拆分成指定数量的微服务就可以了,也不是只能按照业务    来进行拆分,而是可以根据目的的不同灵活地选取不同的拆分方式。接下来我一一介绍常见的拆分方式。

4.2.1 基于业务逻辑拆分

    这是最常见的一种拆分方式,将系统中的业务模块按照职责范围识别出来,每个单独的业务模块拆分为一个独立的服务。

    基于业务逻辑拆分虽然看起来很直观,但在实践过程中最常见的一个问题就是团队成员对于“职责范围”的理解差异很大,经常会出现争论,难以达成一致意见。例如:假设我们做一个电商系统,第一种方式是将服务划分为“商品”“交易”“用户”3个服务,第二种方式是划分为“商品”“订单”“支付”“发货”“买家”“卖家”6个服务,哪种方式更合理,是不是划分越细越正确?

    导致这种困惑的主要根因在于从业务的角度来拆分的话,规模粗和规模细都没有问题,因为拆分基础都是业务逻辑,要判断拆分粒度,不能从业务逻辑角度,而要根据前面介绍的“三个火枪手”的原则,计算一下大概的服务数量范围,然后再确定合适的“职责范围”,否则就可能出现划分过粗或者过细的情况,而且大部分情况下会出现过细的情况。

    例如:如果团队规模是10个人支撑业务,按照“三个火枪手”规则计算,大约需要划分为4个服务,那么“登录、注册、用户信息管理”都可以划到“用户服务”职责范围内;如果团队规模是100人支撑业务,服务数量可以达到40个,那么“用户登录“就是一个服务了;如果团队规模达到1000人支撑业务,那“用户连接管理”可能就是一个独立的服务了。

4.2.2 基于可扩展拆分

    将系统中的业务模块按照稳定性排序,将已经成熟和改动不大的服务拆分为稳定服务,将经常变化和迭代的服务拆分为变动服务。稳定的服务粒度可以粗一些,即使逻辑上没有强关联的服务,也可以放在同一个子系统中,例如将“日志服务”和“升级服务”放在同一个子系统中;不稳定的服务粒度可以细一些,但也不要太细,始终记住要控制服务的总数量。

    这样拆分主要是为了提升项目快速迭代的效率,避免在开发的时候,不小心影响了已有的成熟功能导致线上问题。

4.2.3 基于可靠性拆分

    将系统中的业务模块按照优先级排序,将可靠性要求高的核心服务和可靠性要求低的非核心服务拆分开来,然后重点保证核心服务的高可用。具体拆分的时候,核心服务可以是一个也可以是多个,只要最终的服务数量满足“三个火枪手”的原则就可以。

4.2.4 基于性能拆分

    基于性能拆分和基于可靠性拆分类似,将性能要求高或者性能压力大的模块拆分出来,避免性能压力大的服务影响其他服务。常见的拆分方式和具体的性能瓶颈有关,可以拆分Web服务、数据库、缓存等。例如电商的抢购,性能压力最大的是入口的排队功能,可以将排队功能独立为一个服务。

    以上几种拆分方式不是多选一,而是可以根据实际情况自由排列组合,例如可以基于可靠性拆分出服务A,基于性能拆分出服务B,基于可扩展拆分出C/D/F三个服务,加上原有的服务X,最后总共拆分出6个服务(A/B/C/D/F/X)。

4.3 基础设施

    大部分人主要关注的是微服务的“small”和“lightweight”特性,但实际上真正决定微服务成败的,恰恰是那个被大部分人都忽略的“automated”。为何这样说呢?因为服务粒度即使划分不合理,实际落地后如果团队遇到麻烦,自然会想到拆服务或者合服务;如果“automated”相关的基础设施不健全,那微服务就是焦油坑,让研发、测试、运维陷入我上一期讲的各种微服务陷阱中。

    微服务基础设施如下图所示:

可拓展架构模式_第2张图片

    看到上面这张图,相信很多人都会倒吸一口凉气,说好的微服务的“轻量级”呢?都这么多基础设施还好意思说自己是“轻量级”,感觉比ESB还要复杂啊?

    确实如此,微服务并不是很多人认为的那样又简单又轻量级。要做好微服务,这些基础设施都是必不可少的,否则微服务就会变成一个焦油坑,让业务和团队在里面不断挣扎且无法自拔。因此也可以说,微服务并没有减少复杂度,而只是将复杂度从ESB转移到了基础设施。你可以看到,“服务发现”“服务路由”等其实都是ESB的功能,只是在微服务中剥离出来成了独立的基础系统。

    虽然建设完善的微服务基础设施是一项庞大的工程,但也不用太过灰心,认为自己团队小或者公司规模不大就不能实施微服务了。第一个原因是已经有开源的微服务基础设施全家桶了,例如大名鼎鼎的Spring Cloud项目,涵盖了服务发现、服务路由、网关、配置中心等功能;第二个原因是如果微服务的数量并不是很多的话,并不是每个基础设施都是必须的。通常情况下,我建议按照下面优先级来搭建基础设施:

    1.服务发现、服务路由、服务容错:这是最基本的微服务基础设施。

    2.接口框架、API网关:主要是为了提升开发效率,接口框架是提升内部服务的开发效率,API网关是为了提升与外部服务对接的效率。

    3.自动化部署、自动化测试、配置中心:主要是为了提升测试和运维效率。

    4.服务监控、服务跟踪、服务安全:主要是为了进一步提升运维效率。

    以上3和4两类基础设施,其重要性会随着微服务节点数量增加而越来越重要,但在微服务节点数量较少的时候,可以通过人工的方式支撑,虽然效率不高,但也基本能够顶住。

 

5.微服务架构最佳实践-基础设施篇

    每项微服务基础设施都是一个平台、一个系统、一个解决方案,若需自己实现都需要经过需求分析、架构设计、开发、测试、部署上线等步骤。

    微服务架构3个核心之中,真正能决定微服务成败的,就是『automated』,因为基础设施是微服务可以落地的基础,没有这个基础,所有的服务拆分都是纸上谈兵。

    基础设施根据建设优先级,11种基础设施共分为4类:

5.1 基本基础设施

5.1.1 服务发现

    为了实现节点的变化能够及时同步到所有其他依赖的微服务,需要一套服务发现系统来支撑微服务的自动注册和发现

    服务发现主要有两种实现方式:自理式和代理式。自理式结构就是指每个微服务自己完成服务发现;代理式结构就是指微服务之间有一个负载均衡系统,由负载均衡系统来完成微服务之间的服务发现

    自理式服务实现比较简单,一般通过统一程序包提供给各个服务调用,并且访问压力分散在各个微服务节点,性能和可用性没有明显压力和风险

    代理式服务新增了负载均衡系统,虽然降低了微服务本身的实现难度,但相应增加了可用性风险和性能风险

    服务发现的核心功能就是服务注册表,注册表记录了所有的服务节点的配置和状态,每个微服务启动后都需要将自己的信息注册到服务注册表,然后由微服务或者 负载均衡系统到服务注册表查询可用服务

5.1.2 服务路由

    在具体进行某次调用请求时从所有符合条件的可用微服务节点中挑选出一个具体的节点发起请求,就是服务路由的功能

    服务路由和服务发现紧密相关,一般放在一起实现

    服务路由的核心就是路由算法,常见的有:随机路由、轮询路由、最小压力路由、最小连续数路由等

5.1.3 服务容错

    微服务节点数增加的同时,微服务出故障的概率也会增加,从而出现故障扩散现象

    故障若不及时处理,故障扩散后很多服务节点都会出现故障,所以需要自动应对出错场景,及时处理

    常见的服务容错包括请求重试、流量控制盒服务隔离;一般情况下服务容错会集成在服务发现和服务路由系统中

5.2 提升开发效率

5.2.1 接口框架

    微服务提倡轻量级的通信方式,一般采用 HTTP/REST 或者 RPC 方式统一接口协议

    除了统一接口协议,还需要统一接口传递的数据格式,比如指定数据格式采用JSON,且JSON数据需遵循规范

    接口框架不是一个可运行的系统,一般以库或者包的形式提供给所有微服务调用

5.2.2 API网关

    为了便于外部系统调用系统的某个功能,隔离微服务之间的分工和边界,并且对外统一提供安全和权限相关的能力,需要提供一个统一的API网关,专门负责外部系统的访问

API网关主要包括接入鉴权、权限控制、传输加密、请求路由、流量控制等

5.3 提升测试和运维效率

5.3.1 自动化测试

    微服务之间的接口数量增多,且需要快速交付,所以必须通过自动化测试系统

    自动化测试需要涵盖代码级的单元测试、单个系统级的集成测试、系统间的接口测试,最低要求是至少做到接口测试自动化

5.3.2 自动化部署

    除了接口,微服务需要部署的节点也增加了,部署的频率也会大幅提升

    人工手工处理方式无法满足,且非常容易出错,所以需要自动化部署系统

    自动化部署系统包括版本管理、资源管理(机器、虚拟机)、部署操作、回退操作等    

5.3.3 配置中心

    微服务节点数量太多,采用人工方式修改配置效率低易出错,且部署和排障时需要快速增删改查配置

    有时在运行期间配置需要动态修改并且所有节点即时生效,人工操作无法实现

    配置中心包括配置版本管理、增删改查配置、节点管理、配置同步、配置推送等

5.4 进一步提高运维效率

5.4.1 服务监控

    随着节点数量的增加,需要监控的对象数量相应大大增加,而且出现故障时,需要快速根据各类信息来定位故障,所以需要服务监控系统实现微服务节点的监控

    服务监控的作用主要是 实时搜集信息并进行分析,避免故障后再分析,减少了处理时间;另外服务监控还可以实现预警,在问题萌芽阶段发现并告警

    服务监控系统建议做成独立系统,而不是集成到服务发现、API网关等系统中

5.4.2 服务跟踪

    服务监控与服务跟踪的区别:服务监控记录的数据偏宏观,如请求次数、响应时间平均值、最高值等;服务跟踪记录的数据偏微观,如请求的发起时间、响应时间、响应错误码、请求参数等

    目前绝大部分请求跟踪的实现技术都是基于Dapper论文

5.4.3 服务安全

    从业务角度考虑,部分敏感数据或操作,只能有部分微服务可以访问,因此需要设计服务安全机制

    服务安全主要分3部分:接入安全、数据安全、传输安全

    一般情况下服务安全可以集成在配置中心系统中实现

 

6.微内核架构

    微内核架构(Microkernel Architecture),也被称为插件化架构(Plug-in Architecture),是一种面向功能进行拆分的可扩展性架构,通常用于实现基于产品的应用。

6.1 基本架构

    • 微内核架构包含两类组件:核心系统(core system)和插件模块(plug-in modules)。

    • 核心系统负责和具体业务功能无关的通用功能,例如模块加载、模块间通信等;插件模块负责实现具体的业务逻辑。

    • 核心系统功能比较稳定,不会因为业务功能扩展而不断修改,插件模块可以根据业务功能的需要不断地扩展。

    • 微内核的架构本质就是将变化部分封装在插件里面,从而达到快速灵活扩展的目的,而又不影响整体系统的稳定。

6.2 微内核基本架构

    设计关键点

6.2.1 插件管理

    插件注册机制:核心系统需要知道哪些插件可用、如何加载、什么时候加载

    插件注册表:包含每个插件模块的信息,如名字、位置、加载时机等, 可以是配置文件、代码或数据库

6.2.2 插件连接

    连接规范:明确插件如何连接到核心系统,由核心系统制定,插件按照规范实现

    常见连接机制:OSGi、消息模式、依赖注入、分布式协议

6.2.3 插件通信

    插件间通信:多个插件协作时需要进行通信,通信必须通过核心系统提供的插件通信机制实现,就像计算机的主板总线

6.3 OSGi架构

    OSGi全称Open Services Gateway initiative,一般都是指 OSGi 的规范

    Eclipse 采用 OSGi 标准后,OSGi 成为了首选的插件化标准

    OSGi 是一个插件化的标准,而不是一个可运行的框架,Eclipse 采用的 OSGi 框架称为 Equinox,类似的实现还有 Apache 的 Felix、Spring 的 Spring DM

OSGi框架的逻辑架构图

可拓展架构模式_第3张图片

    •  模块层(Module层):实现插件管理功能。OSGi 中,插件被称为 Bundle,每个 Bundle 是一个 Java 的 JAR 文件,每个 Bundle 里面都包含一个元数据文件 MANIFEST.MF,这个文件包含了 Bundle 的基本信息

    • 生命周期层(Lifecycle 层):实现插件连接功能,提供了执行时模块管理、模块对底层 OSGi 框架的访问。生命周期层精确地定义了 Bundle 生命周期的操作(安装、更新、启动、停止、卸载),Bundle 必须按照规范实现各个操作

    • 服务层(Service 层):实现插件通信的功能。服务注册功能用于各个插件将自己能提供的服务注册到 OSGi 核心的服务注册中心,服务注册指实现插件间通信的机制

6.4 规则引擎架构简析

    规则引擎从结构上来看也属于微内核架构的一种具体体现,其中执行引擎可以看做是微内核,执行引擎解析配置好的业务流,执行其中的条件和规则,通过这种方式来支持业务的灵活多变。

    规则引擎在计费、保险、促销等领域应用较多。例如电商促销,常见的促销规则有:

    3件8折

    第三件免费

    跨店满200减100

    新用户立减50

    …

    以上仅仅列出来常见的几种,实际上完整列下来可能有几十上百种,再加上排列组合,促销方案,可能有几百上千种,这样的业务如果靠代码来实现,开发效率完全跟不上业务的变化速度,而规则引擎却能很灵活的应对这种需求,主要原因在于:

1、可扩展:通过引入规则引擎,业务逻辑实现与业务系统分离,可以在不改动业务系统的情况下扩展新的业务功能

2、易理解:规则通过自然语言描述,业务人员易于理解和操作,而不像代码那样只有程序员才能理解和开发。

3、高效率:规则引擎系统一般提供可视化的规则定制、审批、查询及管理,方便业务人员快速配置新的业务。

规则引擎基本架构如下:

可拓展架构模式_第4张图片

    • 开发人员将业务功能分解提炼为多个规则,将规则保存在规则库中

    • 业务人员根据业务需要,通过将规则排列组合,配置成业务流程,保存在业务库中

    • 规则引擎执行业务流程,实现业务功能

    对照微内核架构的设计关键点,看看规则引擎是如何实现的

1、插件管理

    规则引擎中的规则就是微内核架构中的插件,引擎就是微内核架构的内核。规则可以被引擎加载和执行。规则引擎架构中,规则一般保存在规则库中,使用数据库来存储。

2、插件连接

    业务人员需要基于规则语言来编写规则文件,然后有规则引擎加载执行规则文件来直线业务功能。因为规则引擎的插件连接实现机制,其实就是规则语言。

3、插件通信

    单个规则并不需要依赖其他规则,因此规则之间没有主动的通信,规则只需要输出数据或者事件。

你可能感兴趣的:(#,从0开始学架构)