热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

领域驱动设计领域事件DDD分层架构

篇首语:本文由编程笔记#小编为大家整理,主要介绍了领域驱动设计领域事件DDD分层架构相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了领域驱动设计 领域事件DDD分层架构相关的知识,希望对你有一定的参考价值。





  • 领域事件

    • 什么是领域事件

    • 为什么需要领域事件

    • 微服务场景下的领域事件

    • 领域事件的实现



  • DDD的分层架构

    • DDD分层架构如何推动微服务演进




领域事件


什么是领域事件

在事件风暴过程中,会识别出命令、业务操作、实体等,此外还有事件。比如当业务人员的描述中出现类似“当完成...后,则...”,“当发生...时,则...”等模式时,往往可将其用领域事件来实现。
领域事件表示在领域中发生的事件,它会导致进一步的业务操作。如电商中,支付完成后触发的事件,会导致生成订单、扣减库存等操作。


为什么需要领域事件

领域事件的最终目的是为了实现聚合之间的解耦。事件模式是一种通用的解耦方法,相比依赖间的直接调用,通过事件方式形成的间接依赖,在扩展、重构时更加灵活。
在上一篇领域驱动设计(1) DDD的一些基础概念中提到设计聚合的原则之一:


在边界之外使用最终一致性。聚合内数据强一致性,聚合之间数据最终一致性。在一次事务中,最多只能更改一个聚合的状态。如何一个业务操作涉及多个聚合状态的更改,可以采用领域事件的方式,实现聚合之间的解耦;


聚合根管理多个实体,可以在单个进程内实现数据的强一致性;将DDD实现为微服务时,聚合间的交互可能需要采用进程间的通信的方式(HTTP,RPC,MQ),此时如果仍然采用强一致性代价太高,且可靠性差,而最终一致性就成了更好的选择。(领域)事件就是实现最终一致性的一种方式。

领域事件可以切断领域模型之间的强依赖关系,发布方发布事件后不需要关注订阅方处理事件是否成功,这样实现领域模型的解耦,保证领域模型间的独立性,同时也能实现数据的最终一致性。


微服务场景下的领域事件

领域事件发生在聚合之间,聚合也是微服务拆分的最小单元。但实践中并不一定每个聚合都拆分为独立的微服务,可能多个关联性高的聚合会被置于同一个微服务中,所以用于聚合间交互的领域事件,在微服务场景下可以细分为微服务内和微服务间的领域事件。


微服务内的领域事件

微服务内的领域事件不是必须的,因为微服务内的操作都发生在同一个进程,可以较方便地控制事务。
假设微服务包含多个聚合,不管是聚合内,还是这些聚合间的交互实际上都发生在进程内,可以做到强一致性。但这不符合DDD在一次事务中,最多只能更改一个聚合的状态的原则,此外聚合间采用同步调用的方式也会带来强耦合。
所以可以考虑采用事件总线的实现方式,但事件驱动本身的复杂度大于同步调用,在微服务内处理聚合间的交互还有另一种选择,那就是在应用层来编排和组合跨聚合的调用。
可以结合具体场景分析各种方式的成本和收益。


微服务间的领域事件

微服务间的领域事件用于在跨聚合甚至跨限界上下文间实现业务协作,其主要目的是实现微服务解耦,用异步的领域事件代替同步调用,可以避免微服务间的弹性依赖。


领域事件的实现

领域事件设计事件的生成和发布、事件持久化、事件总线、消息中间件、事件订阅和处理等。



  • 事件的生成和发布:构建的事件应包含事件ID、时间戳、事件类型、事件源等基本属性,以便事件可以无歧义地在不同上下文间传播;此外事件还应包含具体的业务数据。

  • 事件持久化:分布式系统需要考虑分区容忍性,而事件持久化可以保证在发生分区时系统仍然可用,等分区恢复后,系统可继续处理已经持久化的事件。另一方面,持久化的事件还可以用于系统之间的数据对帐或审计。事件持久化的实现,可以选择保存在当前服务所属的数据库,这可以利用本地事务保证数据的强一致性;也可以选择保存在进程外的事件数据库中,但这需要处理分布式事务。

  • 事件总线:用于实现微服务内的事件驱动模式,如mediatR;

  • 消息中间件:用于跨微服务的事件传递,常用的有kafaka、rabbitMQ等;

  • 事件订阅和处理:订阅事件的一方在处理事件前,视业务场景需要,可以选择先保存事件再处理,或者直接处理。


DDD的分层架构

实现DDD的架构有很多种,比如整洁架构(洋葱架构)、六边形架构、DDD分层架构等等。对整洁架构(洋葱架构)、六边形架构不做了解,只focus在DDD分层架构。



  • 用户接口层:暴露用户界面、web服务之类的接口,这里用户还包括其它依赖的服务、自动化测试、批处理脚本等;

  • 应用层:应用层包含应用服务,这一层应当很薄,在应用服务进行聚合间的编排、组合;如果需要调用进程外别的服务,也可以在应用层进行;权限校验、事务控制也可以放在这一层;

  • 领域层:这一层包含核心的业务逻辑,且应该尽量保持稳定,不依赖别的层。对基础层的依赖通过依赖倒置的方式解决;

  • 基础设施层:提供基础设施如数据库、事件总线、API网关、缓存、文件系统等等;作为领域层接口的能力供应商。


DDD分层架构如何推动微服务演进

领域模型中对象的层次从下到上依次有值对象、实体、聚合、限界上下文。
其中值对象和实体的功能变化,会影响微服务内部的实现变化;聚合的功能变化、重组则会影响微服务的拆分、合并。
首先,在微服务内部,实体的方法被领域服务组合和封装,而领域服务又被应用服务组合和封装。领域层通常只提供一些原子的方法,这些方法在应用层被组合起来提供完整的功能,比如原先提供了领域服务A、领域服务B、领域服务C,应用层按需组合这些领域服务,但过一段时间后发现领域服务B、领域服务C总是被同时调用,那么就可以将他俩重构为一个领域服务。
然后,在微服务之间,可能会用限界上下文来分割微服务,但实际上聚合才是微服务划分的基本单元,因为聚合是最小的、业务内聚的单元,聚合可以独立完成特定的业务逻辑。所以有的时候会将同一限界上下文的聚合拆分为不同的微服务。假设原先微服务中包含聚合A、聚合B,但实际运行中发现聚合A的访问频次远高于聚合B,导致聚合B的性能受到了影响。此时就可以将聚合A独立为单独的微服务。

PS:徐昊在极客时间《如何落地业务建模》中认为,划分微服务的依据应该是弹性边界。从此处DDD对微服务的处理来看,徐昊老师的观点可谓一针见血。比如这里的聚合A与聚合B拆开的例子,明显两者处于不同的弹性边界。

参考资料: 欧创新 《DDD实战课》



推荐阅读
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 电商高并发解决方案详解
    本文以京东为例,详细探讨了电商中常见的高并发解决方案,包括多级缓存和Nginx限流技术,旨在帮助读者更好地理解和应用这些技术。 ... [详细]
  • Java EE 平台集成了多种服务、API 和协议,旨在支持基于 Web 的多层应用程序开发。本文将详细介绍 Java EE 中的 13 种关键技术规范,帮助开发者更好地理解和应用这些技术。 ... [详细]
  • 2020年9月15日,Oracle正式发布了最新的JDK 15版本。本次更新带来了许多新特性,包括隐藏类、EdDSA签名算法、模式匹配、记录类、封闭类和文本块等。 ... [详细]
  • 本文详细介绍了Java代码分层的基本概念和常见分层模式,特别是MVC模式。同时探讨了不同项目需求下的分层策略,帮助读者更好地理解和应用Java分层思想。 ... [详细]
  • CRZ.im:一款极简的网址缩短服务及其安装指南
    本文介绍了一款名为CRZ.im的极简网址缩短服务,该服务采用PHP和SQLite开发,体积小巧,约10KB。本文还提供了详细的安装步骤,包括环境配置、域名解析及Nginx伪静态设置。 ... [详细]
  • 本文探讨了在一个物理隔离的环境中构建数据交换平台所面临的挑战,包括但不限于数据加密、传输监控及确保文件交换的安全性和可靠性。同时,作者结合自身项目经验,分享了项目规划、实施过程中的关键决策及其背后的思考。 ... [详细]
  • 深入理解云计算与大数据技术
    本文详细探讨了云计算与大数据技术的关键知识点,包括大数据处理平台、社会网络大数据、城市大数据、工业大数据、教育大数据、数据开放与共享的应用,以及搜索引擎与Web挖掘、推荐技术的研究及应用。文章还涵盖了云计算的基础概念、特点和服务类型分类。 ... [详细]
  • 实践指南:使用Express、Create React App与MongoDB搭建React开发环境
    本文详细介绍了如何利用Express、Create React App和MongoDB构建一个高效的React应用开发环境,旨在为开发者提供一套完整的解决方案,包括环境搭建、数据模拟及前后端交互。 ... [详细]
  • 本文探讨了一种统一的语义数据模型,旨在支持物联网、建筑及企业环境下的数据转换。该模型强调简洁性和可扩展性,以促进不同行业间的插件化和互操作性。对于智能硬件开发者而言,这一模型提供了重要的参考价值。 ... [详细]
  • 本文总结了近年来在实际项目中使用消息中间件的经验和常见问题,旨在为Java初学者和中级开发者提供实用的参考。文章详细介绍了消息中间件在分布式系统中的作用,以及如何通过消息中间件实现高可用性和可扩展性。 ... [详细]
  • 阿里面试题解析:分库分表后的无限扩容瓶颈与解决方案
    本文探讨了在分布式系统中,分库分表后的无限扩容问题及其解决方案。通过分析不同阶段的服务架构演变,提出了单元化作为解决数据库连接数过多的有效方法。 ... [详细]
  • 本文详细介绍了 Java 网站开发的相关资源和步骤,包括常用网站、开发环境和框架选择。 ... [详细]
  • 微服务优雅上下线的最佳实践
    本文介绍了微服务上下线的正确姿势,避免使用 kill -9 等粗暴手段,确保服务的稳定性和可靠性。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有