热门标签 | 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实战课》



推荐阅读
  • Oracle优化新常态的五大禁止及其性能隐患
    本文介绍了Oracle优化新常态中的五大禁止措施,包括禁止外键、禁止视图、禁止触发器、禁止存储过程和禁止JOB,并分析了这些禁止措施可能带来的性能隐患。文章还讨论了这些禁止措施在C/S架构和B/S架构中的不同应用情况,并提出了解决方案。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • Python开源库和第三方包的常用框架及库
    本文介绍了Python开源库和第三方包中常用的框架和库,包括Django、CubicWeb等。同时还整理了GitHub中最受欢迎的15个Python开源框架,涵盖了事件I/O、OLAP、Web开发、高性能网络通信、测试和爬虫等领域。 ... [详细]
  • svnWebUI:一款现代化的svn服务端管理软件
    svnWebUI是一款图形化管理服务端Subversion的配置工具,适用于非程序员使用。它解决了svn用户和权限配置繁琐且不便的问题,提供了现代化的web界面,让svn服务端管理变得轻松。演示地址:http://svn.nginxwebui.cn:6060。 ... [详细]
  • Centos下安装memcached+memcached教程
    本文介绍了在Centos下安装memcached和使用memcached的教程,详细解释了memcached的工作原理,包括缓存数据和对象、减少数据库读取次数、提高网站速度等。同时,还对memcached的快速和高效率进行了解释,与传统的文件型数据库相比,memcached作为一个内存型数据库,具有更高的读取速度。 ... [详细]
  • 目录浏览漏洞与目录遍历漏洞的危害及修复方法
    本文讨论了目录浏览漏洞与目录遍历漏洞的危害,包括网站结构暴露、隐秘文件访问等。同时介绍了检测方法,如使用漏洞扫描器和搜索关键词。最后提供了针对常见中间件的修复方式,包括关闭目录浏览功能。对于保护网站安全具有一定的参考价值。 ... [详细]
  • ElasticSerach初探第一篇认识ES+环境搭建+简单MySQL数据同步+SpringBoot整合ES
    一、认识ElasticSearch是一个基于Lucene的开源搜索引擎,通过简单的RESTfulAPI来隐藏Lucene的复杂性。全文搜索,分析系统&# ... [详细]
  • 容器管理与容器监控influxDB
    容器管理与容器监控-influxDB什么是influxDBinfluxDB安装(1)下载镜像(2)创建容器(3 ... [详细]
  • 构建LNMP架构平台
    LNMP架构的组成:Linux、Nginx、MySQL、PHP关于NginxNginx与apache的作用一样,都是为了搭建网站服务器,由俄罗斯人lgorsysoev开发,其特点是 ... [详细]
  • celery 爬虫使用
    简介celery是一个基于分布式消息传输的异步任务队列,它专注于实时处理,同时也支持任务调度。它由三部分组成,消息中间件, ... [详细]
  • 这也太简单了!轻松操作Feign 服务调用使用 Zipkin 链路追踪!
    0、介绍分布式微服务时代,方便了业务的快速增长和服务的稳定,但是系统出现问题后,面对同业务多服务排查起来令人头大。这时候领导就想着集成分布式追踪系统。Zipkin是T ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • [翻译]微服务设计模式5. 服务发现服务端服务发现
    服务之间需要互相调用,在单体架构中,服务之间的互相调用直接通过编程语言层面的方法调用就搞定了。在传统的分布式应用的部署中,服务地 ... [详细]
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社区 版权所有