与我一起学习微服务架构设计模式2—服务的拆分策略

微服务架构是什么?

软件的架构是什么,为什么它如此重要?

定义:

应用程序的架构是将软件分解为元素和这些元素之间的关系。

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

逻辑视图:开发人员创建的软件元素,如类或包,他们之间的关系包括继承、关联和依赖。

实现视图:构建编译系统的输出。由表示打包代码的模块(Jar文件)和组件(WAR文件)组成。

进程视图:运行时的组件。每个元素都是一个进程,进程间的关系代表进程间通信。

部署视图:进程如何映射到机器,元素由计算机和进程组成,机器间的关系代表网络。

场景:它负责把视图串联起来。

架构的重要性:

功能性需求可以通过任意的架构来实现,而架构满足了第二类需求:非功能性需求,也称质量属性需求,它决定了应用程序开发、运行阶段的质量

架构的风格

特定的架构风格提供了有限的元素和关系,你可以从中定义应用程序架构的视图。

分层架构:

将软件元素按“层”的方式组织。每层定义职责,每一层只能依赖其下面的层。

流行的三层架构(表现层、业务逻辑层、数据持久层)是应用于逻辑视图的分层架构,但单一的表现层无法展现应用可能不仅仅由单个系统调用的事实,单一的数据持久层无法展现应用程序可能与多个数据库进行交互的事实。将业务逻辑定义为依赖于持久层,在理论上会妨碍你在没有数据库的情况下测试业务逻辑。

六边形架构:

与我一起学习微服务架构设计模式2—服务的拆分策略_第1张图片

六边形架构将业务逻辑与适配器中包含的表示层和数据访问层的逻辑分离开来,使得单独测试业务逻辑容易得多;可以通过多个适配器调用业务逻辑,业务逻辑也可以调用多个适配器。

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

将应用程序构建为松耦合、可独立部署的一组服务

服务

服务是一个单一的、可独立部署的软件组件,它实现了一些有用的功能。服务需具有API且可独立部署, API封装了内部实现,开发人员无法绕过API访问,强制实现了应用程序的模块化。典型的服务往往具有六边形架构。

松耦合

微服务架构的最核心特性是服务间的松耦合性。服务间的交互通过API完成,封装了实现细节。这是改善开发效率、提升可维护性和可测试性的关键。

服务自身的持久化数据是不对外的。保证数据的私有属性是实现松耦合的前提之一。但这也使处理数据不一致和跨服务查询变得更复杂。

共享类库的角色

共享库容易在服务之间引入耦合,可以将这些通用功能作为服务来实现。可以使用共享库实现不太可能改变的功能。

服务的大小并不重要

更好的目标是将服务定义为能够由小团队开发的服务,且交付时间最短,与其他团队协作最少。

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

识别系统操作

1、创建由关键类组成的抽象领域模型,这些关键类提供了用于描述系统操作的词汇表(可以分析用户故事和场景中频繁出现的名词为切入点) 

2、定义系统操作(可以分析用户故事和场景中的动词为切入点)

    命令型:创建、更新或删除数据的系统操作 

    查询型:查询和读取数据的系统操作

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

业务能力通常指这个组织的业务是做什么,它们通常是稳定的。一旦确定了业务能力,就可以为每个能力或相关能力组定义服务。如餐馆的三个能力:餐馆信息管理、订单管理、会计记账。

围绕能力组织服务的关键好处是它们是稳定的,所以最终的架构也相对稳定。但它们可能也会随着时间推移而变化。

根据子域进行服务拆分

领域模型以解决具体问题的方式包含了一个领域内的知识,定义了当前领域相关团队的词汇表,DDD有两个重要概念:子域和限界上下文

领域驱动为每一个子域定义单独的领域模型。子域是领域的一部分,领域是DDD中用于描述应用程序问题域的一个术语。识别子域的方式跟识别业务能力一样:分析业务并识别业务的不同专业领域, 分析产出的子域定义结果也会跟业务能力非常接近, 如一个外卖系统的子域包含订单管理,会计,送餐等。

领域模型的边界称为限界上下文。它包含实现这个模型的代码集合。微服务架构下,每个限界上下文对应一个或一组服务。

拆分的指导原则

单一职责原则:

改变一个类应该只有一个理由。

在设计微服务架构时,设计小的,内聚的,仅仅含有单一职责的服务。这会缩小服务的大小,提升其稳定性。

闭包原则:

在包中包含的所有类应该是对同类的变化的一个集合,也就是说,如果对包做出修改,需要调整的类应该都在这个包之内。

在设计微服务时,把根据同样原因进行变化的服务放在一个组件内。这样可以控制服务的数量,当需求发生变化时,变更和部署也更容易。

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

1、网络延迟 

解决方案是实施批处理API,或者把多个相关的服务组合在一起,用函数代替进程间通信

2、同步进程间通信导致可用性降低

可以使用异步消息消除同步调用产生的紧耦合

3、在服务之间维持数据一致性

可以使用Saga代替传统的ACID和两阶段提交

4、获取一致的数据视图

无法跨越多个数据库获得真正一致的数据视图,如果需要一些数据的一致视图,它必须驻留在单个服务。

5、上帝类阻碍拆分 

上帝类是整个应用程序中使用的全局类。如外卖系统中的Order类,系统大部分都涉及订单。

将Order类打包到库中,并创建一个中央Order数据库,所有服务通过此库访问数据库,这导致了紧耦合。

还有一种方案是将Order数据库封装在Order Service中,但这个Service将成为很少或没有业务逻辑的贫血领域模型。

更好的方法是应用DDD,将每个服务视为具有自己的领域模型的单独子域。即系统中与订单相关的每个服务都有自己的领域模型及其对应的Order类的版本。但系统必须维护不同服务间不同对象的一致性,多个领域模型还会影响用户体验。

定义服务API

有了系统操作列表和潜在的服务列表之后,后面就是定义服务的API,起点是将每个系统操作映射到服务。然后确定服务是否需要与其他服务协作以实现系统操作。如果需要协作,我们将确定其他服务必须提供哪些API才能支持协作。

java达人

ID:drjava

(长按或扫码识别)

感谢你的阅读,下面是一个抽奖链接按钮,10月14日晚上开奖,共6个红包,写文不易,感谢大家支持。

感谢大家一直以来的阅读、在看和转发,点我参与抽奖!点我参与抽奖!

你可能感兴趣的:(与我一起学习微服务架构设计模式2—服务的拆分策略)