《微服务架构设计模式》笔记2—服务拆分策略

《微服务架构设计模式》笔记2—服务拆分策略

  • 二、服务拆分策略
    • 1、软件架构
    • 2、架构的风格
      • 1、分层式架构风格
      • 2、六边形架构:
    • 3、微服务架构是一种架构风格
      • 1、什么是服务
      • 2、什么是松耦合
      • 3、共享类库的角色
      • 4、服务大小并不重要
    • 4、为应用程序定义微服务架构
    • 5、识别操作系统
      • 1、创建抽象领域模型
      • 2、定义系统操作
      • 3、根据业务能力进行服务拆分
      • 4、根据子域进行服务拆分
      • 5、拆分的指导原则
      • 6、拆分单体应用为服务的难点
      • 7、定义服务API
    • 6、本章小结

二、服务拆分策略

1、软件架构

  • 软件架构:软件的架构是一种抽象的结构,它由软件的各个组成部分和这些部分之间的依赖关系构成。
  • 架构目标:可扩展性、可靠性和安全性。

软件架构的4+1视图模型:

  • 《微服务架构设计模式》笔记2—服务拆分策略_第1张图片

  • 每个视图的目的如下:

    • 逻辑视图:开发人员创建的软件元素。面向对象的语言中,这些元素是类和包。他们之间的关系是类和包之间的关系,包括继承、关系和依赖。
    • 实现视图:构建编译系统的输出。此视图由表示打包代码的模块和组件组成。组件是由一个或多个模块组成的可执行或可部署单元。在java中,模块是jar文件,组件通常是war文件或可执行jar文件。它们之间的关系包括模块之间的依赖关系以及组件和模块之间的组合关系。
    • 进程视图:运行时的组件。每个元素都是一个进程,进程之间的关系代表进程间通信。
    • 部署视图:进程如何映射到机器。此视图中元素由(物理或虚拟)计算机和进程组成。机器之间的关系代表网络。该视图还描述了进程和机器之间的关系。
  • 场景:它负责将视图串联再一起。

2、架构的风格

  • 架构风格:
    • 架构风格确定可以再该风格的实例中使用的组件和连接器的词汇表,以及关于如何组合他们的一组约束。
    • 特定的架构风格提供了有限的元素(组件)和关系(连接器),你可以从中定义应用程序架构的视图。应用程序通常使用多种架构风格的组合。

1、分层式架构风格

  • 架构的典型例子就是分层架构。分层架构将软件按“层”的方式组织。每个层都有明确定义的职责。

  • 分层架构还限制了层之间的依赖关系。每一层只能依赖于紧邻其下方的层或者其下面的任何层。

  • 流行的三层架构是应用于逻辑层的分层架构,他将应用程序的类组织到以下层中:

    • 表现层:包含实现用户界面或外部API代码
    • 业务逻辑层:包含业务逻辑
    • 数据持久化层:实现与数据交互的逻辑
  • 分层架构的弊端:

    • 单个表现层:它无法展现应用程序可能不仅仅由单个系统调用的事实。
    • 单一数据持久化层:他无法展现应用程序可能与多个数据库进行交互的事实。
    • 将业务逻辑层定义为依赖于数据持久化层:理论上,这样的依赖性会妨碍你在没有数据库的情况下测试业务逻辑。

2、六边形架构:

  • 六边形架构是分层架构风格的替代品。它是选择以业务逻辑为中心的方式组织逻辑视图。

  • 应用程序具有一个或多个入站适配器,而不是表示层,它通过调用业务逻辑来处理外部的请求。

  • 同样,应用程序具有一个或多个出站适配器,而不是数据持久化层,这些出站适配器由业务逻辑调用并调用外部应用程序。

  • 此架构的一个关键特性和优点是业务逻辑不依赖于适配器。相反,各种适配器都依赖业务逻辑。

  • 《微服务架构设计模式》笔记2—服务拆分策略_第2张图片

  • 业务逻辑具有一个或多个端口,端口定义了一组操作,关于业务逻辑如何与外部交互。

  • 例如,在java中,端口通常是java接口。

  • 有两种端口:入站和出站端口

    • 入站端口是业务逻辑公开的API,使外部应用程序可以调用它。
    • 出站端口是业务逻辑调用外部系统的方式。出站端口的一个实例是存储接口,它定义数据访问操作的集合。
  • 业务逻辑周围是适配器,与端口一样,有两种类型适配器:

    • 入站适配器通过调用入站端口来处理来自外部世界的请求。
      • 入站适配器的一个实例是SpringMVC Controller,它实现一组REST接口(endPoint)或一组Web页面。
      • 另一个实例是订阅消息的消息代理客户端。多个入站适配器可以调用相同的入站端口。
    • 出站适配器实现出站端口,并通过调用外部应用程序或服务来处理来自业务逻辑的请求。
      • 出站适配器的一个实例是实现访问数据库操作的数据访问对象(DAO)类。
      • 另一个实例是调用远程服务的代理类。出站适配器可以发布事件。
  • 六边形架构风格的一个重要好处是它将业务逻辑与适配器中包含的表示层和数据访问层的逻辑分离开来。业务逻辑层不依赖于表示层逻辑或数据访问层逻辑。这种分离使得单独测试业务逻辑要容易的多。

  • 另一个好处就是它更准确的反映了现代应用程序的架构,可以通过多个适配器调用业务逻辑,每个适配器实现特定的API或用户界面。业务逻辑还可以调用多个适配器,每个适配器调用不同的外部系统。

  • 所以六边形架构是描述微服务架构中每个服务的架构的好方法。

3、微服务架构是一种架构风格

  • 单体架构是一种架构风格,它的实现视图是单个组件:单个可执行文件或war文件。
  • 微服务架构也是一种架构风格。
    • 它的实现视图由多个组件构成:一组可执行文件或war文件。
    • 它的组件是服务,连接器是是这些服务能够协作的通信协议。
    • 每个服务都有自己的逻辑视图架构,通常也是六边形架构。
  • 《微服务架构设计模式》笔记2—服务拆分策略_第3张图片

1、什么是服务

  • 服务是一个单一的、可独立部署的软件组件,它实现了一些有用的功能。
  • 下图显示了服务的外部视图
  • 《微服务架构设计模式》笔记2—服务拆分策略_第4张图片
    • 在此实例中,order Service服务具有API,微客户端提供功能访问。
    • 有两种类型的操作:命令和查询。
    • API由命令、查询和事件组成。
      • 命令,如createOrder()执行操作并更新数据。
      • 查询,如findOrderById()检索数据。
      • 服务还发布由其客户端使用的事件,如OrderCreated。
    • 服务的API封装了其内部实现,与单体架构不同,开发人员无法绕过服务的API字节访问服务内部的方法和数据,因此,微服务架构强制实现了应用程序的模块化。

2、什么是松耦合

  • 微服务架构的最核心是服务之间的松耦合性,服务之间的交互采用API完成,这样做就封装了服务的实现细节。这允许服务在不影响客户端的情况下,对实现方式做出修改。松耦合服务是改善开发效率、提升可维护性和可测试性的关键。小的、松耦合的服务更容易被理解、修改和测试。

3、共享类库的角色

  • 开发人员经常把一些通用的功能打包到库或模块中,以便多个应用程序可以重用它而无需复制代码。但是如果业务需求变更影响了通用功能,开发者需要同时重建和重新部署所有使用共享库的服务。

  • 选择将可能更改的通用功能作为服务来实现,而不是共享库。

4、服务大小并不重要

  • 微服务的微不应该是服务的大小。
  • 而是将精心设计的服务定义为能够由小团队开发的服务,并且交付时间最短,与其他团队协作最少。

4、为应用程序定义微服务架构

  • 定义应用程序架构的三步式流程
    《微服务架构设计模式》笔记2—服务拆分策略_第5张图片

  • 第一步,定义系统操作

    • 应用程序是用来如何处理客户端需求的,因此定义其架构的第一步是将应用程序的需求提炼为各种关键请求。
    • 系统操作(system operation)是应用程序必须处理的请求的一种抽象描述。
      • 他既可以是更新数据的命令,也可以是检索数据的查询。
      • 每个命令的行为都是根据抽象领域模型定义的,抽象领域模型也是从需求中派生出来的。
      • 系统操作是描述服务之间协作方式的架构场景
  • 第二步,定义如何分解服务

    • 有几种策略可供选择。
      • 一种源于业务架构学派的策略是定义与业务能力相对应的服务。
      • 另一种策略是围绕领域驱动设计的子域来分解和设计服务。
    • 这些策略最终结果都是围绕业务概念而非技术概念分解和设计的服务。
  • 第三步,确定每个服务的API

    • 将第一步中标识的每个系统操作分配给服务。服务可以完全独立地实现操作。
    • 或者与其他服务协作时,还需确定哪种进程间通信机制来实现每个服务API
  • 服务分解需要克服的障碍

    • 网络延迟:
      • 服务之间网络往返太多,特定的分解是不切实际的。
    • 服务间同步通信的可用性降低
    • 维护跨服务的数据一致性,可以使用Saga
    • 上帝类God class,使用领域驱动设计中的概念消除上帝类。

5、识别操作系统

  • 定义应用程序架构的第一步是定义系统操作。起点是应用程序的需求,包括用户故事及其相关的用户场景。
  • 下图是两步式流程识别和定义系统操作
  • 《微服务架构设计模式》笔记2—服务拆分策略_第6张图片
    • 第一步创建由关键类组成的抽象领域模型,这些关键类提供用于描述系统操作的词汇表。
    • 第二步确定系统操作,并根据领域模型描述每个系统操作的行为。

1、创建抽象领域模型

  • 定义系统操作的第一步是为这个应用程序描绘一个抽象的领域模型。
  • 如图:
    • 《微服务架构设计模式》笔记2—服务拆分策略_第7张图片
    • 每一个类的作用如下:
      • Consumer:下订单的用户
      • Order:用户下的订单,它用来描述订单并跟踪状态。
      • OrderLineItem:Order中的一个条目
      • DeliveryInfo:送餐的时间和地址。
      • Restaurant:为用户准备生产订单的餐馆,同事也要发起送货。
      • MenuItem:餐馆菜单上的一个条目。
      • Courier:送餐员负责把订单送到用户手里。可跟踪送餐员的可用性和他们的位置。
      • Address: Consumer或Restaurant的地址
      • Location:Courier当前的位置,用经纬度表示。

2、定义系统操作

  • 当定义了抽象的领域模型之后,接下来就要识别系统必须处理的各种请求。

  • 系统操作分两种类型:

    • 命令型:创建、更新或删除数据的系统操作
    • 查询型:查询和读取数据的系统操作。
  • 从根本上说,这些系统操作都会对应到具体的REST、RPC或消息端口。

  • 识别系统指令的切入点是分析用户故事和场景中的动词。很多用户故事都会直接对应或映射为系统命令。

  • 《微服务架构设计模式》笔记2—服务拆分策略_第8张图片

  • 命令规范定义了命令对应的参数、返回值和领域模型类的行为。如图:

  • 《微服务架构设计模式》笔记2—服务拆分策略_第9张图片

  • 《微服务架构设计模式》笔记2—服务拆分策略_第10张图片

3、根据业务能力进行服务拆分

  • 系统操作被定义后,接下来就是完成应用服务的识别。
  • 可以有多种拆分策略可供选择,每种选择都是从一个侧面来解决问题,并且使用它们独有的一些术语。这些策略的结果都是都是一样的:一个包含若干服务的架构,这样的架构是以业务而不是技术概念为中心。
  • 业务能力是一个来自于业务架构建模的术语,是指一些能够为公司产生价值的商业活动。
  • 业务能力定义了一个组织的工作:
    • 组织的业务能力通常是指这个组织的业务时做什么,他们通常都是稳定的。
    • 与之相反,组织采用何种方式来实现它的业务能力,是随着时间不断变化的。
  • 识别业务能力:
    • 一个组织有哪些业务能力,是通过对组织的目标、结构和商业流程的分析得来的。
    • 每个业务能力都可以被认为是一个服务,除非他是面向业务的而非面向技术的。
    • 业务能力规范包含多项元素,比如输入输出、服务等级协议(SLA)。例如保险承保能力的输入来自客户的应用程序,这个业务能力的输出是完成核保并报价。
  • 从业务能力到服务
    • 一旦确定了业务能力,就可以为每个能力或相关能力组定义服务。
    • 下图显示了FTGO应用程序从能力到服务的映射:
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ypnK1wQc-1624008230154)(…/AppData/Roaming/Typora/typora-user-images/image-20210618152057028.png)]

4、根据子域进行服务拆分

  • 领域驱动设计是构建复杂软件的方法论,这些软件通常都以面向对象和领域模型为核心。

  • 领域模型以解决具体问题的方式包含了一个领域内的知识。它定义了当前领域相关团队的词汇表,DDD也称之为通用语言。

  • 再微服务架构设计层面,DDD有两个特别重要的概念,子域和限界上下文。

  • 子域是领域的一部分,领域是DDD中从来描述应用程序问题域的一个术语。

    • 识别子域的方式和识别业务能力一样,分析业务并识别业务的不同专业领域,分析产出的子域定义结果也会跟业务能力非常接近。
  • 限界上下文Bounded content,包括实现这个模型的代码集合。

    • 当时用微服务架构时,每一个限界上下文对应一个或者一组服务。
    • 换种说法,我们可以通过DDD的方式定义子域,并把子域对应为每一个服务。这样就完成了微服务架构设计工作。
    • 下图展示了子域和微服务之间的映射。
    • 《微服务架构设计模式》笔记2—服务拆分策略_第11张图片
  • DDD和微服务架构简直就是天生一对。DDD的子域和限界上下文的概念,可以很好的跟威武架构中的服务进行匹配。

  • 而且,微服务架构中的自治化团队负责服务开发的概念,也跟DDD中每个领域模型都有一个独立团队负责开发的概念吻合。

  • 更有趣的是,子域用于它自己的领域模型这个概念,为消除上帝类和优化服务拆分提供了好办法。

5、拆分的指导原则

  • 单一职责原则:改变一个类应该只有一个理由。
    • 类所承载的每一个职责都是对他进行修改的潜在原因。如果一个类承载了多个职责,并且互相之间的修改是独立地,那么这个类就会变得非常不稳定。遵循SRP原则,你所定义的每一个类都应该只有一个职责,因此也就只有一个理由对它进行修改。
  • 闭包原则CCP:
    • 在包中包含的所有类应该是对同类的变化的一个集合,也就是说,如果对包做出修改,需要调整的类应该都在这个包内。
    • 这样做的目标是,当业务规则发生变化时,开发者只需要对一个交付包做出修改,而不是大规模地修改(和重新编译)整个应用。采用比表原则,极大地改善了应用程序的可维护性。

6、拆分单体应用为服务的难点

  • 从表面上看,通过定义与业务能力或子域相对应的服务来创建微服务架构的策略看起来很简单。但是可能会遇到几个障碍:
    • 网络延迟
    • 同步进程间通信导致可用性降低
    • 在服务之间维持数据一致性。
    • 获取一致的数据视图。
    • 上帝类阻碍了拆分。
  • 网络延迟
    • 网络延迟是分布式系统中一直存在的问题,你可能会发现,对服务的特定分解会导致两服务之间的大量往返调用。
    • 解决方案是吧多个相关的服务组合在一起,用编程语言的函数调用替换昂贵的进程间通信。
  • 同步进程间通信导致可用性降低
    • 比如使用REST同步调用其他服务,这样做的弊端是REST这样的协议会降低服务的可用性。
    • 如果任何一个被调用的服务在不可用状态,那么订单就无法创建了。
  • 在服务之间维持数据一致性
    • 需要更新多个服务中的数据时,仍旧维护数据之间的数据一致性。这些更新必须以原子化方式完成。
    • 传统解决方式是基于两阶段提交的分布式事务管理机制。
    • 解决方案,采用Saga,Saga是一系列使用消息协作的本地事务。Saga比传统的ACID事务更复杂,但它们在许多情况下都能工作很好,Saga的一个限制是它们最终是一致的。
  • 获取一致的数据视图
    • 分解的另一个障碍是无法跨多个数据库获得真正一致的数据视图。
    • 在单体应用程序中,ACID事务的属性保证查询将返回数据库的一直视图。
    • 在微服务架构中,即使每个服务的数据库是一致的,你也无法获得全局一致的数据视图。
  • 上帝类阻碍拆分
    • 上帝类是整个应用程序中使用的全局类。通常为应用程序的许多不同方面实现业务逻辑。
    • 传统建模技术的上帝类结构,如图
    • 《微服务架构设计模式》笔记2—服务拆分策略_第12张图片
    • 问题解决方案
      • 一种是将上帝类打包到库中并创建一个中央order数据库,处理订单的所有服务都使用此库并访问数据库。这种方法问题在于它违反了微服务架构的一个关键原则,并导致紧耦合。比如对order模式的任何更改都会要求其他开发团队同步更新和重新编译他们的代码。
      • 另一种解决方案是将order数据库封装成一个order Service。这种问题在于一个orderService将成为一个纯数据服务。
    • DDD提供了一个好的解决方案
      • 应用DDD并将每个服务视为具有自己领域模型的单独子域。如图:
      • 《微服务架构设计模式》笔记2—服务拆分策略_第13张图片

7、定义服务API

  • 服务API也就是服务的操作和事件。
  • 存在服务API操作有以下两个原因:
    • 某些操作对应于系统操作,他们由外部客户端调用,也可以由其他服务调用。
    • 存在一些其他操作用以支持服务之间的协作。
  • 定义服务API的起点是将每个系统操作映射到服务,之后确定服务是否需要与其他服务协作以实现系统操作。如果需要协作,我们将确定其他服务必须提供哪些API才能支持协作。首先来看下如果将系统操作分配给服务:
    • 把系统操作分配给服务
    • 确定支持服务协作所需要的API。
  • 《微服务架构设计模式》笔记2—服务拆分策略_第14张图片

6、本章小结

  • 架构决定了软件的各种非功能性因素,比如可维护性、可测试性、可部署性和可扩展性,他们会直接影响开发速度。
  • 微服务架构是一种架构风格,他给应用程序带来了更高的可维护性、可测试性、可部署性和可扩展性。
  • 微服务中的服务是根据业务需求进行组织的,按照业务能力或者子域,而不是技术上的考量。
  • 有两种分解模式:
    • 按业务能力分解,其起源于业务架构
    • 基于领域驱动设计的概念,通过子域进行分解。
  • 可以通过应用DDD并为每个服务定义单独的领域模型来消除上帝类,正式上帝类引起了阻碍分解的交织依赖项。

你可能感兴趣的:(《微服务架构设计模式》,微服务架构)