DDD从小白到入门

DDD实战篇三

边界:微服务的各种边界在架构演进中的作用

微服务设计的重点就是看微服务设计是否能够支持架构长期、轻松的演进。MartinFowler在提出微服务时,提到了微服务的一个重要特征–演进式架构。演进式架构就是以支持增量的、非破坏的变更作为第一原则,同时支持在应用程序结构层面的多维度变化.

如何判断微服务设计是否合理?
只需要看它是否满足这样的情形:随着业务的发展和需求的变更,在不断重新拆分或者组合成新的微服务的过程中,不会大幅度增加软件开发和维护的成本,并且这个架构演进的过程是非常轻松、简单的。使用DDD方法设计的微服务,不仅可以通过限界上下文和聚合实现微服务内外的解耦,同时也可以很容易地实现业务功能积木式模块的重组和更新,从而实现架构演进。

微服务边界的作用:
			逻辑边界:主要定义统一业务领域或应用内紧密关联的对象所组成的不同聚类的组合之间的边界。事件风暴对不同实体对象进行关联和聚类分析后,
				会产生多个聚合和限界上下文,它们一起组成这个领域的领域模型。微服务内聚合之间的边界就是逻辑边界,一般来说微服务会有一个以上的聚合,
				在开发过程中不同聚合的代码隔离在不同的聚合代码目录中。
	
				我们也可以对多个微服务内有相似功能的聚合进行功能和代码重组,组合为新的聚合和微服务,独立为通用微服务(类似中台)
			物理边界:主要从部署和运行的视角来定义微服务之间的边界。不同微服务部署位置和运行环境是相互物理隔离的,分别运行在不同的进程中。
				这种边界就是微服务之间的物理边界。	
			代码边界:主要用于微服务内的不同职能代码之间的隔离。微服务开发过程中会根据代码模型建立相应的代码目录,实现不同功能代码的隔离。
				由于领域模型与代码模型的映射关系,
				代码边界直接体现出业务边界。代码边界可以控制代码重组的影响范围,避免业务和服务之间的相互影响。微服务如果需要进行功能重组,
				只需要聚合代码为单元进行重组就可以了。

正确理解微服务的边界:微服务的过度拆分会使软件维护成本上升,比如:集成成本、发布成本、运维成本以及监控和定位问题的成本等。在项目建设初期,如果不具备较强的微服务管理能力,那就不宜将微服务拆分过细。当具备一定能力后,且微服务内部的逻辑和代码边界也很清晰,就可以随时根据需要,拆分出性的微服务,实现微服务的架构演进了。

总的来说,
逻辑边界:微服务内聚合之间的边界是逻辑边界,它是一个虚拟的边界,强调业务的内聚,可以根据需要变成物理边界,也就是说聚合也可以独立为微服务。

物理边界:微服务之间的边界是物理边界,它强调微服务部署和运行的隔离,关注微服务的服务调用、容错和运行等。

代码边界:不同层或者聚合之间代码目录的边界是代码边界,它强调的是代码之间的隔离,方便架构演进时代码的重组。

业务能力高内聚、代码松耦合,且边界清晰。边界清晰的微服务,不是大单体向小单体的演进。

视图:如何实现服务和数据在微服务各层的协作

1、服务的类型

facade服务:位于用户接口层,包括接口和实现两部分。用于处理用户发送的Restful请求和解析用户输入的配置文件等,并将数据传递给应用层。或者在获取到应用层数据后,将DO组装成DTO,将数据传输到前端应用。

应用服务:位于应用层。用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果拼装,对外提供粗粒度的服务。

领域服务:位于领域层。领域服务封装核心的业务逻辑,实现需要多个实体协作的核心领域逻辑。它对多个实体或方法的业务逻辑进行组合或编排,或者在严格架构中对实体方法进行封装,以领域服务的方式供应用层调用。

基础服务:位于基础层。提供基础资源服务(比如数据库、缓存等),实现各层的解耦,降低外部资源变化对业务应用逻辑的影响。基础服务主要为仓储服务,通过依赖倒置提供基础资源服务。领域服务和应用服务都可以调用仓储服务接口,通过仓储服务实现数据持久化。

2、服务的调用:微服务的服务调用主要包括三类场景:微服务内跨层调用、微服务之间服务调用和领域事件驱动:

微服务内跨层服务调用:微服务架构往往采用前后端分离的设计模式,前端应用独立部署。前端应用调用发布在API网关上的facade服务,

facade定向到应用服务,应用服务作为服务组织和编排这,它的服务调用有以下两种路径:

第一种是应用服务调用并组装领域服务。此时领域服务会组装实体和实体方法,实现核心领域逻辑。领域服务通过仓储服务获取持久化数据对象,完成实体数据初始化。
第二种是应用服务直接调用仓储服务。这种方式主要针对像缓存、文件等类型的基础层数据访问。这类数据主要是查询操作,没有太多的领域逻辑,不经过领域层,
不涉及数据持久化对象。

微服务之间的服务调用:微服务之间的应用服务可以直接访问,也可以通过API网关访问。由于跨微服务操作,在进行数据新增和修改操作时,需要关注分布式事务,保证数据的一致性。

领域事件驱动:领域事件驱动包括微服务内和微服务之间的事件。微服务内通过事件总线(EventBus)完成聚合之间的异步处理。微服务之间通过消息中间件完成。异步化的领域事件驱动机制是一种间接的服务访问方式。

当应用服务业务逻辑处理完成后,如果发生领域事件,可调用事件发布服务,完成事件发布。当接收到订阅的主体数据时,事件订阅服务会调用事件处理领域服务,完成进一步的业务操作。

3、服务的封装和组合:微服务的服务是从领域层逐级向上封装、组合和暴露的。

基础层:基础层的服务形态主要是仓储服务。仓储服务包括接口和实现两部分。仓储接口服务供应应用层或者领域层服务调用,
				仓储实现服务,完成领域对象的持久化或数据初始化
领域层:领域层实现核心业务逻辑,负责表达领域模型业务概念、业务状态和业务规则。主要的服务形态有实体方法和领域服务。实体采用充血模型,在实体内部实现实体相关的所有业务逻辑,
		实现的形式是实体类中的方法。
		实体是微服务的原子业务逻辑单元。在设计时我们主要考虑自身的属性和业务行为,实现领域模型的核心基础能力。不必过多考虑外部操作的业务流程,这样才能保证领域模型的稳定性。
				DDD提倡富领域模型,尽量将业务逻辑归属到实体对象上,实在无法归属的部分则设计成领域服务。领域服务会对多个实体或实体方法进行组装和编排,实现跨多个实体的复杂核心业务逻辑。
				
应用层:应用层用来表述应用和用户行为,负责服务的组合、编排和转发,负责处理业务用例的执行顺序以及结果的拼装,负责不同聚合之间的服务和数据协调,负责微服务之间的事件发布和订阅。
		通用服务内用于组合和编排的服务,主要来源于领域服务,也可以是外部微服务的应用服务。除了完成服务的组合和编排外,应用服务内还可以完成安全认证、权限检验、初步的数据校验
		和分布式事务控制等功能。为了实现微服务内聚合之间的解耦,聚合之间的服务调用和数据交互应通过应用服务来完成。

用户接口层:用户接口层是前端应用和微服务之间服务访问和数据交换的桥梁。它处理前端发送的Restful请求和解析用户输入的配置文件等,将数据传递给应用层,或获取应用服务的数据后,进行数据组装,
			向前端提供数据服务,主要形态是facade服务。facade服务分为接口和实现两个部分,完成服务定向,DO和DTO数据的转换和组装,实现前端与应用层数据的装换和交换。

4、两种分层架构的服务依赖关系

松散分层架构的服务依赖:在松散分层架构中,领域层的实体方法和领域服务可以直接暴露给应用层和用户接口层。松散分层架构的服务依赖关系,无需逐级封装,可以快速暴露给上层。

松散分层存在的问题:一是容易暴露领域层核心业务的实现逻辑。二是当实体方法或者领域服务发生服务变更时,由于服务同时被多层服务调用和组合,不容易找出哪些山城服务调用和组合了它,不方便通知到所有的服务调用方。

严格分层架构的服务依赖:在严格分层架构中,服务如果需要跨层调用,下层服务需要在上层封装后,才可以提供跨层服务,比如实体方法需要向应用服务提供服务,它需要封装成领域服务。

通过封装可以避免将核心业务逻辑的实现暴露给外部,将实体和方法封装成领域服务,也可以避免在应用层沉淀过多的本该属于领域层的核心业务逻辑,避免应用层变得臃肿。当服务发生变更时,由于服务只被紧邻上层的服务调用和组合,只需要逐级告知紧邻上层就可以了,服务可管理性比松散分层架构要好是一定的。

数据对象视图:

数据持久化对象PO(Persistent Object):与数据库结构一一映射,是数据持久化过程中的数据载体。
	
领域对象DO(Domain Object):微服务运行时的实体,是核心业务的载体。
			
数据传输对象DTO(Data Transfer Object):用于前端与应用层或者微服务之间的数据组装和传输,是应用之间数据传输的载体。
			
视图对象VO(View Object):用于封装展示层指定页面或组件的数据	

微服务各层数据对象的职责和转换过程:

基础层:基础层的主要对象是PO对象。我们需要先建立DO和PO的映射关系,当DO数据需要持久化时,仓储服务会将DO转换为PO对象,完成数据库持久化操作。当DO数据需要初始化时,
		仓储服务从数据库获取数据形成PO对象,并将PO转换为DO,完成数据初始化。大多数情况下PO和DO是一一对应的,但也有DO和PO多对多的情况。在DO和PO数据转换时,需要进行数据重组。

领域层:领域层的主要对象是DO对象。DO是实体和值对象的数据和业务行为载体,承载着基础的核心业务逻辑。通过DO和PO转换,我们可以完成数据持久化和初始化。

应用层:应用层的主要对象是DO对象。如果需要调用其他微服务的应用服务,DO会转换为DTO,完成跨微服务的数据组装和传输。用户接口层先完成DTO到DO的转换,然后应用服务接收DO进行业务处理。
		如果DTO与DO是一对多的关系,这是就需要进行DO数据重组。
			
用户接口层:用户接口层会完成DO和DTO的互转,完成微服务与前端应用数据交互及转换。Facade服务会对多个DO对象进行封装,转换为DTO对象,
				向前端应用完成数据转换和传输。

前端应用:前端应用主要是VO独享,展现层使用VO进行界面展示,通过用户接口层与应用层采用DTO对象进行数据交互。	

微服务之间分布式事务的使用,需要根据业务来做取舍。如果数据不一致没关系或者数据不重要,部分数据丢了也可以,就可以不用,如果是核心业务数据或者涉及到钱的业务数据,分布式事务就必不可少了。

本篇文章主要介绍了微服务边界和服务和数据之间的协作,下篇文章将会介绍如何设计微服务前后端。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值