DDD领域驱动设计内容分享(二十九):DDD架构在网易支付交易业务的落地与实践

目录

1.背景

2.为何选择DDD

3.DDD的相关概念与落地

3.1战略设计

通用语言

事件风暴

领域

限界上下文

上下文映射图

3.2战术设计

3.3 系统架构

3.3.1 分层架构

3.3.2 CQRS架构

3.3.3 事件驱动架构(EDA)

4. 总结


架构设计的重要性不言而喻,交易系统作为网易支付的核心系统,承担着重要的收单、支付等工作,且业务逻辑复杂,稳健性强、扩展性高的应用架构是支撑业务快速迭代的基石。本文将介绍DDD设计相关的重要概念,以及在交易业务中的落地与实践

1.背景

网易支付的交易业务主要涉及收单、支付以及订单的售后等操作,支持多种模型的订单,提供统一支付的能力。订单从生成到支付再到后续的退款或发货等操作,每种业务操作链路都较长,业务入口也比较多,业务逻辑比较分散,这样存在以下问题:

1、职责不清晰:交易业务逻辑与其他业务逻辑耦合,未做隔离措施。

2、维护成本高:由于业务逻辑比较分散,当需要调整交易业务逻辑时评估改动范围费时费力。

3、代码可读性差:想要了解完整的交易业务逻辑,需要多处的代码逻辑进行汇总,阅读成本较高。

4、扩展性差:当需要增加新的业务逻辑时,需要在多个关键链路上调整代码,改动风险较高,测试回归工作量大。

2.为何选择DDD

从业务出发、面向业务变化是架构设计成功的关键,架构设计的本质是保证面对业务变化时系统能够拥有快速响应的能力。DDD(Domain-Driven Design,领域驱动设计)作为架构设计的方法论,着重于将业务领域的知识和行为融入到软件设计中,适用于复杂业务场景的应用程序。它可以帮助开发团队更好地理解业务需求,强调团队与领域专家的合作,从而设计出更加符合实际需求的系统,构建一致的架构体系。DDD将业务逻辑和技术实现分离,注重领域模型的设计和演化,通过定义领域模型确定业务和应用的边界,保证业务模型与代码模型的一致性,帮助设计出清晰的领域和应用边界,比较适用于复杂度高、需要长期维护和演进的应用程序。交易系统业务逻辑复杂度较高,DDD模式可以使交易系统更加聚焦订单、支付两大核心业务,同时DDD采用面向对象的设计也有利于实现模块的高内聚低耦合,解决交易业务逻辑分散的问题,提高响应业务变更的速度。

3.DDD的相关概念与落地

DDD设计可分为两个阶段:战略设计和战术设计,从而设计出最终的系统架构。

3.1战略设计

战略设计是指从宏观的角度出发,强调以领域为核心,对业务领域进行深入地理解和分析,从而制定出系统的整体架构和设计方案,以保证软件系统能够满足业务需求,并具备可扩展性、可维护性、可测试性等优秀的软件工程特性。DDD的战略设计通常包括领域建模、限界上下文划分、事件风暴等内容。

通用语言

团队合作时有各种角色人员,比如产品、开发、测试等,每个人对于同一业务的理解所采用的表述方式存在差异,所以应该通过团队交流达成共识,使用统一的业务知识,定义一种通用语言,减少不必要的翻译过程,防止概念变形、理解不统一,能够简单、清晰、准确地描述业务含义和规则。

事件风暴

事件风暴(Event Storming)是一种用于发现和探索业务需求的技术。它通过参与者之间的协作和讨论,将业务领域中的事件和命令可视化,从而帮助团队更好地理解业务需求,设计和开发系统。事件风暴通常由三个阶段组成:

  1. 事件涌现(Event Emergence):团队成员会共同发现业务中的事件,并将其记录在一个大型的白板或者墙上。这个过程通常需要一些时间,因为团队成员需要共同探索业务中的各种事件,并尝试将它们组织起来。

  2. 事件组织(Event Organization):团队成员会对之前发现的事件进行分类和组织,以形成一个更加清晰的业务模型。这个过程通常需要一些调整和重组,以确保模型的准确性和完整性。

  3. 模型细化(Model Refinement):团队成员会对之前形成的业务模型进行细化和完善,以确保它可以转化为可执行的软件模型。这个过程通常需要一些技术支持,以确保模型的可行性和正确性。

通过事件风暴,团队可以更好地理解业务领域中的复杂性和不确定性,并能够更快地识别出业务中的瓶颈和问题。此外,事件风暴还可以帮助团队建立共享的语言和理解,以便更好地协作和沟通。

领域

领域的概念就是指特定的问题域,用来限定业务边界,代表某一个业务领域,即应用程序需要解决的问题空间。在DDD中,软件设计应该围绕着业务领域展开,注重领域建模,而不是技术实现。通过深入理解业务领域中的概念和规则,将其映射到软件设计中,可以更好地满足业务需求,并且减少技术实现与业务之间的差距。在DDD中,领域模型是一个重要的概念,它是对业务领域中的概念、规则和行为的抽象和表示。领域模型应该是领域专家和开发人员共同协作的结果,它应该反映业务领域中的实际情况,并且能够支持业务需求的变化和演化。交易所有的业务都限定在交易领域中。

图片

限界上下文

限界上下文指业务领域中的一个边界,通过对业务领域的合理分解,限定了在该边界内使用的业务术语和规则,不同限界上下文之间可以使用相同的术语和规则来描述不同的业务含义。在一个大型系统中,可能会有多个限界上下文,每个限界上下文都有自己的业务逻辑和数据模型,相互之间是独立的。限界上下文之间的交互需要通过明确定义的接口进行,这样可以减少不同限界上下文之间的耦合度,从而更好地维护系统的可扩展性和可维护性。交易的核心就是订单和支付,且两者的业务逻辑是相互独立的。订单涉及订单的创建以及订单的一些售后操作,如退款、发货、打款、冻结、解冻等,订单创建还没到支付流程,售后操作只需要校验订单已经完成支付即可,对于支付这一操作的业务逻辑并不关心,两者完全可以解耦。支付操作则关注支付方式的组合、支付渠道的路由以及支付方案的创建和分配等业务逻辑。所以通过限界上下文的划分,交易领域拆分成订单中心、支付中心两大业务子域。

图片

上下文映射图

上下文映射图用于描述多个限界上下文之间的关系和交互,它可以帮助团队更好地理解系统中各个限界上下文之间的关系,从而更好地协作和开发。限界上下文关系包含以下几种:

  1. 合作关系(Partnership):两个上下文紧密合作的关系,一荣俱荣,一损俱损。

  2. 共享内核(Shared Kernel):两个上下文依赖部分共享的模型。

  3. 客户方-供应方关系(Customer-Supplier):上下文之间有组织的上下游依赖。

  4. 遵奉者(Conformist):下游上下文只能盲目依赖上游上下文。

  5. 防腐层(Anticorruption Layer):一个上下文通过一些适配和转换与另一个上下文交互。

  6. 开放主机服务(Open Host Service):定义一种协议来让其他上下文来对本上下文进行访问。

  7. 发布语言(Published Language):通常与OHS一起使用,用于定义开放主机的协议。

  8. 大泥球(Big Ball of Mud):混杂在一起的上下文关系,边界不清晰。

  9. 另谋他路(SeparateWay):两个完全没有任何联系的上下文。

在交易业务中,订单和支付属于紧密联系的两个领域,符合“一荣俱荣,一损俱损”的合作关系。确定了关系后,限界上下文之间需要通过某种方式进行集成,以实现系统的整体功能,常见的集成方式有以下几种:

  1. 事件驱动(Event-Driven):通过事件来实现限界上下文之间的通信。一个限界上下文可以发布事件,而另一个限界上下文可以订阅该事件,并做出相应的处理。

  2. 请求响应(Request-Response):通过请求和响应来实现限界上下文之间的通信。一个限界上下文可以向另一个限界上下文发送请求,而另一个限界上下文可以返回响应。

  3. 共享数据库(Shared Database):多个限界上下文共享同一个数据库,通过数据库来实现限界上下文之间的通信。

  4. REST API:通过 RESTful API 来实现限界上下文之间的通信。一个限界上下文可以向另一个限界上下文发送 RESTful 请求,而另一个限界上下文可以返回 RESTful 响应。

在交易业务中,比如订单需要支付,那么需要先在支付中心完成支付,然后再触发订单中心完成支付,才算完成订单的整体支付行为,退款也是类似。交易的限界上下文的集成方式采用了事件驱动模式,原因是实现简单、维护成本低,当支付中心完成支付会发布支付成功事件,订单中心会订阅该事件,当监听到有事件发布就会做出相应的处理。在该交互流程中,涉及到通用域的协作。从重要性和功能特性上来划分,领域可分为核心域和通用域。核心域是指与业务核心价值相关的领域,通常包含了业务的关键概念和规则,是企业的核心竞争力所在,订单中心、支付中心属于核心域。通用域是指在多个业务领域中通用的概念、规则和模型,事件驱动集成限界上下文时,领域事件是订单中心和支付中心通用的概念,通用域提供统一的维护。

图片

3.2战术设计

战术设计侧重于具体的技术实现,主要关注如何将领域模型转化为可执行的代码,完成业务的开发和落地。战术设计主要包括以下几个方面:

  1. 聚合:聚合是一组相关对象的集合,它们一起形成了一个完整的业务概念,作为一个整体被外界访问,由业务和逻辑紧密关联的实体和值对象组合而成。聚合是数据修改和持久化的基本单元,每一个聚合对应一个数据仓储。

  2. 聚合根:聚合中的一个对象被称为聚合根(Aggregate Root),它是聚合的唯一入口点,所有的操作都必须通过聚合根进行。

  3. 实体:实体是具有唯一标识的领域对象,表示业务领域中具有唯一标识和生命周期的对象,通常与数据库中的表相对应,是聚合中的子对象,或者是聚合根本身。

  4. 值对象:值对象是没有唯一标识的领域对象,它们通常用于描述领域中的属性或者特征。

  5. 领域行为:实体通过自身属性提供出来的能力,将业务内聚到自身实体中。

  6. 领域服务:一些重要的领域操作,无法通过实体内的行为完成,归类为领域服务,用来处理业务逻辑。

  7. 仓储:仓储是指将领域模型中的对象持久化到数据库或者其他存储介质中的机制。仓储通常由一个接口和一个具体的实现组成。

以上概念在交易的落地情况,拿订单举例子,数据库的订单表对应TradeOrder实体,交易未将多个实体或值对象进行聚合操作,那么TradeOrder本身就是一个聚合,同时聚合根也是本身,orderId是实体的唯一标识,hasPaid()、hasRefunded()是通过实体自身的属性orderState判断的,属于领域行为。假如需要更新订单怎么操作呢?通过实体自身属性是没有办法完成业务操作的,所以提供了领域服务TradeOrderDomainService,来完成订单相关的处理逻辑,如更新订单状态等。

图片

3.3 系统架构

DDD架构模式有多种,主要包括以下几个:

  1. 分层架构:分层架构是一种将系统划分为多个层次的架构,通常包括表示层、应用层、领域层和基础设施层。每一层都有不同的职责和功能,通过定义清晰的接口和依赖关系,可以实现系统的松耦合和可扩展性。

  2. CQRS架构(Command and Query Responsibility Segregation Architecture):CQRS架构是一种将读操作和写操作分离的架构,通常包括命令模型和查询模型两个部分。命令模型用来处理写操作,查询模型用来处理读操作,通过分离读写操作,可以更好地优化系统性能和可伸缩性。

  3. 事件驱动架构(Event-Driven Architecture):事件驱动架构是一种通过事件来驱动系统行为的架构,通常包括事件生产者、事件消费者和事件总线。事件生产者生产事件并将其发布到事件总线上,事件消费者从事件总线上订阅事件并处理它们。通过事件驱动架构,可以实现系统的松耦合和可扩展性。

  4. 微服务架构(Microservices Architecture):微服务架构是一种将系统划分为多个小型服务的架构,每个服务都有独立的职责和功能,并通过定义清晰的接口和依赖关系来实现松耦合和可扩展性。微服务架构通常需要使用一些支持工具和技术来管理服务之间的通信和协调,如容器化、服务发现、负载均衡等。

每种架构都有自己的优缺点,分层架构易于理解和实现,适用于大多数应用程序,但可能会出现过度分层的情况,导致系统复杂度增加;CQRS架构通过分离读写操作,可以更好地优化系统性能,但实现复杂度较高,需要考虑命令模型和查询模型之间的同步问题;事件驱动架构可以实现异步处理和高并发处理,但需要考虑事件生产者和消费者之间的同步问题,可能会出现事件丢失或重复消费的问题;微服务架构可以实现服务的独立部署和升级,但需要考虑服务之间的通信、服务故障和版本兼容性等问题。综合考虑各种模式的优缺点以及交易自身的业务特性,最终结合了多种架构模式来实现,并做了一些适用于实际场景的改良。

3.3.1 分层架构

整体上,交易系统采用传统的分层架构:

图片

接口层:也称表示层,负责与用户交互,通常包括用户界面和API接口。在交易系统中负责定义API接口,具体的业务逻辑由应用层提供服务。

应用层:负责协调系统的各个部分,使用防腐层和领域层提供的服务完成业务的编排,并将返回结果转换为接口层的格式。

领域层:负责实现业务逻辑和领域模型,通常包括实体、值对象、聚合根和领域服务等。领域层是整个系统的核心,它定义了系统的业务规则和行为,是DDD设计的重点。交易系统分为订单中心和支付中心两个领域。

防腐层:防腐层用于解决不同系统之间的集成问题,将外部系统的数据和行为与本地系统的领域模型隔离开来,防止外部系统的变化对本地系统造成影响。由于交易系统底层依赖账务、账号、网关等系统,需要防腐层和交易系统做隔离,避免底层依赖系统变化带来的影响。

基础设施层:负责实现系统的基础设施和技术支持,通常包括数据仓储、消息队列、缓存、日志和安全等。基础设施层为整个系统提供了必要的支持和保障。领域层所需要的仓储服务,只在领域层定义相关的接口,不关心具体的实现逻辑,具体实现交给基础设施层来完成,让领域层更关注领域逻辑。

3.3.2 CQRS架构

CQRS架构强调读写分离,命令模型处理写操作,查询模型处理读操作,因为读操作和写操作通常具有不同的特点和负载,通过分离它们,可以更好地针对不同的负载进行优化和扩展。交易系统主要是针对订单的售后业务操作使用了CQRS模式,订单支付后有发货、打款、冻结、解冻、截留以及截留回退的操作,业务操作顺序、订单状态变更都有限制,通过定义状态机作为命令总线,用来分发不同的业务命令,路由出对应的命令执行器,通过领域服务完成对应的业务逻辑变更。

图片

3.3.3 事件驱动架构(EDA)

事件驱动EDA模式的好处是可以把处理流程解耦,实现系统可扩展性,提高主业务流程的内聚性,同时可把多个限界上下文串联起来,上文中提到的限界上下文的集成方式也是通过事件驱动模式来实现。

图片

4. 总结

通过使用DDD架构,可以更好地理解业务需求、优化系统架构、提高系统性能和可伸缩性,帮助设计出高内聚低耦合的复杂应用系统,并且能够更好地应对系统变化。但DDD并不是适用于所有场景的解决方案,它需要根据具体情况进行分析,根据业务需求和技术特点选择合适的架构模式,并结合实际情况进行设计和实现。

  • 24
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之乎者也·

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值