DDD、微服务和中台之间的关系。
中台本质是业务模型,微服务是业务模型的系统落地,DDD 是一种设计思想
,可以同时指导中台业务建模和微服务设计,它们之间就是这样的一个铁三角关系。DDD 强调领域模型和微服务设计的一体性,先有领域模型然后才有微服务,而不是脱离领域模型来谈微服务设计。
DDD革命性在于
:领域模型准确反映了业务语言,而传统微服务数据对象除了简单setter/getter方法外,没有任何业务方法,即失血模型,那么DDD领域模型就是充血模型(业务方法定义在实体对象中)
。
10 大核心概念
,深入设计思想,各知识域之间的关系
DDD分层架构、 DDD 战略设计和事件风暴
DDD 的核心知识体系,具体包括:领域、子域、核心域、通用域、支撑域、限界上下文、实体、值对象、聚合和聚合根
等概念。
领域会细分为不同的子域,子域可以根据自身重要性和功能属性划分为三类子域,它们分别是:核心域、通用域和支撑域
。
决定产品和公司核心竞争力的子域是核心域,它是业务成功的主要因素和公司的核心竞争力。没有太多个性化的诉求,同时被多个子域使用的通用功能子域是通用域(登录、认证等)。还有一种功能子域是必需的,但既不包含决定产品和公司核心竞争力的功能,也不包含通用功能的子域,它就是支撑域。
限界上下文:定义了领域的边界
Person是实体,Address是值对象,领域模型采用充血模型
聚合就是由业务和逻辑紧密关联的实体和值对象组合而成的,聚合是数据修改和持久化的基本单元,每一个聚合对应一个仓储,实现数据的持久化
。
聚合在 DDD 分层架构里属于领域层,领域层包含了多个聚合,共同实现核心业务逻辑。
领域事件表示在领域中发生的事件,它会导致进一步的业务操作。如电商中,支付完成后触发的事件,会导致生成订单、扣减库存等操作。
跨微服务的领域事件会在不同的限界上下文或领域模型之间实现业务协作,其主要目的是实现
微服务解耦
,减轻微服务之间实时服务访问的压力。微服务之间的访问也可以采用应用服务直接调用的方式,实现数据和服务的实时访问,弊端就是跨微服务的数据同时变更需要引入分布式事务,以确保数据的一致性。
分布式事务机制会影响系统性能,增加微服务之间的耦合,尽量避免使用分布式事务。
通过领域事件驱动的异步化机制(借助消息中间件),可以推动业务流程和数据在各个不同微服务之间的流转,实现微服务的解耦,减轻微服务之间服务调用的压力,提升用户体验。
领域事件处理包括:事件构建和发布、事件数据持久化、事件总线、消息中间件、事件接收和处理
等。
事件的生成和发布
:构建的事件应包含事件唯一标识(事件唯一标识应该全局唯一)、时间戳、事件类型、事件源等基本属性,以便事件可以无歧义地在不同上下文间传播;此外事件还应包含具体的业务数据。
为了保证事件结构的统一,创建事件基类 DomainEvent,子类可以扩充属性和方法。
可以通过应用服务或者领域服务发布到事件总线或者消息中间件,也可以从事件表中利用定时程序或数据库日志捕获技术获取增量事件数据,发布到消息中间件。
事件数据持久化可用于系统之间的数据对账,或者实现发布方和订阅方事件数据的审计。当遇到消息中间件、订阅方系统宕机或者网络中断,在问题解决后仍可继续后续业务流转,保证数据的一致性。
两种持久化方案:
事件总线是实现微服务内聚合之间领域事件的重要组件,它提供事件分发和接收等服务。事件总线是进程内模型
,它会在微服务内聚合之间遍历订阅者列表,采取同步或异步的模式传递数据。
事件分发流程大致如下:
guava的EventBus组件
完成消息发布-订阅机制【简化方案能节省很多开发时间和代码量,用的比较多】
跨微服务的领域事件大多会用到消息中间件,实现跨微服务的事件发布和订阅。消息中间件的产品非常成熟,市场上可选的技术也非常多,比如 Kafka,RabbitMQ 等。
微服务订阅方在应用层采用监听机制
,接收消息队列中的事件数据,完成事件数据的持久化后,就可以开始进一步的业务处理。领域事件处理可在领域服务中实现。
SAGA事务保证分布式事务
优化过后的分层架构(DDD分层架构包含用户接口层、应用层、领域层和基础层
),DDD 的分层架构在不断发展。后来领域层和应用层之间增加了上下文环境(Context)层
,五层架构(DCI) 就此形成。
传统四层架构中,基础层是被其它层依赖的,它位于最核心的位置,那按照分层架构的思想,它应该就是核心,但实际上领域层才是软件的核心。后来采用了依赖倒置(Dependency inversion principle,DIP)的设计,优化了传统的四层架构,实现了各层对基础层的解耦。
四层架构:
五层架构:
业务在这里组装。仓储(资源库)接口在此层定义
。注意:
- 简单查询
不涉及业务,可以直接从应用层直接穿透到PO查询,不需要经过domain层
。DDD本身不限制非业务类操作跨层调用。DTO不能存在于domain层
,DDD设计不认为DTO是业务对象,entity才是。或者传值简单数据类型也是可以的。
DDD 分层架构有一个重要的原则:每层只能与位于其下方的层发生耦合
。
DDD 分层架构中的要素其实和三层架构类似,只是在 DDD 分层架构中,要素被重新归类,重新划分了层,确定了层与层之间的交互规则和职责边界。
三层架构向 DDD 分层架构演进,主要发生在业务逻辑层和数据访问层。
用户接口层引入了 DTO,给前端提供了更多的可使用数据和更高的展示灵活性。
对三层架构的业务逻辑层进行了更清晰的划分,改善了三层架构核心业务逻辑混乱,代码改动相互影响大的情况。DDD 分层架构将业务逻辑层的服务拆分到了应用层和领域层
。应用层快速响应前端的变化,领域层实现领域模型的能力。
DDD 分层架构的数据库等基础资源访问,采用了仓储(Repository)设计模式
,通过依赖倒置实现各层对基础资源的解耦。
仓储又分为两部分:仓储接口和仓储实现。仓储接口放在领域层中,仓储实现放在基础层
。原来三层架构通用的第三方工具包、驱动、Common、Utility、Config 等通用的公共的资源类统一放到了基础层。