背景

为什么要拟定参阅工程架构

不同团队落地DDD所采纳的使用架构风格或许不同,并没有一致的、规范的DDD工程架构。有些团队或许遵从经典的DDD四层架构,或改进的DDD四层架构,有些团队或许综合考虑分层架构、整齐架构、六边形架构等多种架构风格,有些在实践中或许引进CQRS处理读模型与写模型的差异化等等。即便无法拟定通用的、规范的工程使用架构,但为团队拟定一个遵从范畴驱动规划思维的参阅架构依然有价值。根据以下原因:

  • 为团队实践DDD的战术规划供给能够快速开端的工程参阅
  • 参阅工程很多的命名和结构决议计划,显式的体现DDD的相关理念,有利于团队对DDD的战术完结达成一起认知
  • 一起,参阅架构有助于沉淀团队对范畴驱动规划的一些思考和最佳实践

参阅架构的考量要素

尽管无法拟定彻底通用的DDD参阅架构,但拟定某个特定上下文下的参阅架构却具有可行性和实践价值。针对于上下文的挑选要尽量贴合实践的工程实践场景并考虑多维度的要素。

本文所述参阅工程架构遵从以下原则:

  • 遵从范畴驱动规划的本质思维
  • 充分考虑事务体系建造特色
  • 依靠最小化,坚持轻量

希望工程参阅架构能涵盖以下范围

  • 别离事务域与技能域

参阅架构要遵从技能和事务阻隔的特性,能够参阅多种架构风格。事务与技能关注点的别离并不是DDD独有的特色,在六边形、整齐架构、洋葱架构中都遵从了这一重要原则。

  • 多限界上下文场景

大多数团队根据DDD进行微服务拆分的时候,特别是体系建造初期,对单个微服务使用内的限界上下文的粒度需求权衡。由于团队安排架构要素及微服务本钱问题,单个使用包容的限界上下文一般是多个(理想状况下是1:1)。这些限界上下文随着后续的逐渐迭代有或许会迁移至独立使用。因而,参阅架构将多上下文的使用场景作为重要考量要素。

  • 明确的组件、责任鸿沟及依靠联系
  • 支撑范畴报表场景:报表场景在事务体系较为常见,DDD并没有体现该场景的处理方法。作为工程参阅架构,仍是希望能够从实践事务动身,体现对写模型和报表模型的显现支撑
  • 外部依靠最小化:需求排除不必要的依靠,坚持工程架构的轻量化

参阅架构剖析

使用的多上下文结构

根据以上原则,参阅工程考虑单个使用内多上下文的场景,以期在模块化和服务粒度及本钱间进行权衡折衷。使用架构对多上下文的支撑的逻辑示意图如下所示,在处理方案域对限界上下文进行辨认和区分之后,根据其事务内聚性和关联性,把多个上下文完结单个工程使用中。单个使用内的多个限界上下文间或许存在交互,交互的方法可所以根据事情驱动,也可所以根据进程内调用。选用事情驱动的方法上下文间的耦合性对低一些,但一般需求引进事情总线的支撑,额外组件的引进必然会导致复杂性的上升。进程内调用则耦合性会高一些,但从完结视点复杂度会低一些。详细挑选哪种方法开发人员能够根据实践状况进行权衡。

【实践篇】领域驱动设计:DDD工程参考架构 | 京东云技术团队

需求再次阐明的是,这种使用架构决议计划是一种多要素的权衡,并没有与子域与限界上下文1:1的理想化实践坚持一起。

从上图的逻辑示意图咱们再深化一层,从分层的维度去剖析一下详细的使用架构的展示方法,如下图所示:

【实践篇】领域驱动设计:DDD工程参考架构 | 京东云技术团队

分层关注点

客户端

客户端与使用处于不同的进程,是使用才能的消费端,在实践项目中或许是APP端、PC端、小程序端、公众号端或三方的事务调用端等等。

接入层

接入层是外部体系与使用内部事务才能的中间层,接入层是使用层对外的门面,是当时使用对外露出事务才能的进口。该层的组成或许是对外供给的HTTP接口声明、分布式定时使命调度、消息监听器、RPC服务等等。其重要责任包括对外部体系的恳求进行根底的参数校验、入参适配和服务路由(转发至系一层的使用服务)以及呼应数据的适配

事务层:

该层是使用的事务逻辑所在层,整个架构风格选用模块化单体风格,在该层不同的限界上下文体现为不同的模块。在每个限界上下文内选用分层架构,独立区分为使用层、范畴层和网关层

使用层:

和谐范畴目标、范畴服务或外部依靠服务完结事务用例,该层只做才能和谐,不处理任何范畴逻辑

范畴层:

范畴层是整个分层的中心,与技能完结无关,首要担任范畴模型、范畴事情、范畴服务界说,以及事务相关外部服务的接口笼统以及仓库的接口笼统等。

范畴层与使用服务的本质区别是:使用层不包括范畴逻辑,范畴逻辑悉数下沉到范畴层完结。

网关层:

网关层定位是使用的出口网关,是使用与外部根底设施交互的防腐层,处理一切技能相关完结

该组件的命名有多种方法,比如有些团队将其命名为 “rpc”,也有些团队将其命名为 “infrastructure”,不同的命名体现了团队对其背面所表达的隐喻的决议计划挑选。在本文的参阅架构中挑选了 网关-Gateway这一命名,决议计划原因是:限界上下文自身是高内聚的,其与外部的交互需求一致出口,Gateway所表达的网关的含义恰当的体现了这种一致出口的理念。假如Facade层是使用的北向网关,是外部体系恳求进入内部的进口。则此刻的Gateway则表达的是限界上下文的南向网关,是内部使用连接外部的出口。

组件及依靠

从宏观的分层咱们再深化一层看下每层的组件区分。如下图所示:

【实践篇】领域驱动设计:DDD工程参考架构 | 京东云技术团队

Start组件:

整个使用的启动进口、加载使用配置信息等等。

Common组件

供给在不同的限界上下文间复用的范畴模型元素的笼统,比如对Command、Query、Event、Entity、ValueObjec通用笼统等。当然,范畴模型的通用笼统不是必须在Common组件内以供给复用,也能够作为一个独立的限界上下文,并以同享内核方法与其它上下文进行同享,或者也能够完结为独立的jar包组件。

API 组件

RPC类型服务的接口声明组件,以公司内部使用的JSF为例,该组件是使用对外部体系露出的JSF API的组件。该组件可所以独立的工程,当然,有些团队会将其作为一个Module放入使用工程中。

一致门面组件:Facade

外部客户端触达使用体系的进口,也是内部使用服务的一致门面,类似于六边形架构风格下的适配器。参阅架构中根据不同场景区分为 provider(RPC服务)、task(定时使命)、listener(MQ监听)、rest(http接口)等几个子包。外部恳求进入体系后,由Facade组件完结入参根本校验、入参转化、服务路由以及出参转化等操作。另外,还能够承担处理登录态、鉴权以及日志等相关才能。

使用服务组件:Application Service

使用服务代表着用例以及体系行为,其经过托付到范畴层和根底设施层(参阅架构中的Gateway组件)完结用例的使用逻辑逻辑处理,能够理解为使用服务是范畴层的客户端。该组件典型的责任:

从存储层加载范畴目标、托付范畴目标执行范畴逻辑、保存范畴目标

  • 重要事情告诉到外部
  • 出入参转化适配
  • 事务处理外部
  • 非范畴逻辑的服务调用

External API

使用服务的逻辑不仅仅需求和谐范畴层,有时还需求依靠于外部的三方服务。External API 组件担任对这些外部服务进行接口声明界说,不做详细完结。

使用服务组件不直接依靠这些外部服务完结,而是依靠其接口笼统。一起,此处的模型界说是根据该限界上下文的语义,是一种对外部模型的适配。

该组件不依靠其它组件,且仅被使用服务组件和Gateway组件依靠。网关组件依靠External API 组件的接口声明并供给底层技能完结,使用服务组件依靠其接口,并经过IOC方法将详细完结注入完结服务调用。

留意,该组件所依靠的服务不触及范畴逻辑,仅仅用于支撑使用服务的编排。假如是触及了范畴逻辑,则对外部服务依靠的接口界说需求下沉到Domain层。

Query

Query组件处理范畴相关的报表查询场景,在限界上下文内作为与使用服务对等的组件存在,两个组件分别担任事务的查询和指令逻辑。

尽管引进了Query组件对报表场景供给支撑,但没有彻底的引进CQRS这一模式。在很多资猜中CQRS与DDD一起提及的概率比较高,因为,在DDD下咱们处理了复杂的面向范畴的写侧模型,但在报表场景下,这种富范畴模型有或许并不是最佳挑选。假如读侧和写侧都根据一致的范畴模型,一般会导致范畴模型的折衷规划。为了满足查询侧诉求,范畴模型不得不引进额外的、范畴无关的属性,由此造成范畴模型的污染。

Domain

Domain组件是范畴逻辑中心,承担整个体系范畴逻辑的完结,其界说了范畴模型、范畴服务、范畴事情以及仓储层的笼统。该组件不依靠其它组件(除了通用的范畴模型笼统组件Common之外。

上图所体现的参阅架构使用了DDD的战术规划的经典建模元素,比如聚合、实体、值目标、仓储、工厂以及范畴事情等。在实践落地过程中,这些规划元素的笼统具有必定的应战,规划过程中需求经过不断剖析、权衡和重构以完结建模,这正是中心规划所在。

Gateway

网关层承担整个技能相关性的完结,是内部使用的出口网关。

技能相关性是网关组件区别于其它组件的根本特性。在该组件内要处理技能完结的一切细节,比如与外部服务、中间件、DB的交互等。一起,其与Domain组件以及External API组件的接口笼统协作,一起承担了体系与外部依靠间(包括外部服务以及使用依靠的中间件、DB等根底设施)的防腐层功能,担任内部模型到外部模型转化、外部模型到内部模型转化以及详细交互。根据网关组件的特性,也非常适合在该层做一致的外部服务数据缓存及降级熔断处理。

网关层依靠于Domain、Application Service、External API和Query组件,担任上述四个组件界说的接口完结。在Gateway组件经过子包对完结进行阻隔:

  • query:查询服务组件的完结
  • external:External API 组件中依靠外部服务的接口完结
  • repository:仓储接口的完结

最终

使用架构模式的挑选是体系架构规划的重要维度之一,结构不仅仅是简略的包结构和命名,其传达的是一种顶层笼统,背面包括了很多的实践和知识。拟定契合团队状况的工程参阅架构,并在团队成员间达成一致非常重要。范畴驱动规划并没有一致的、通用的架构,试图界说规范架构是不切实践的。本文描绘的工程架构仅仅一个参阅,实践过程中应该根据团队特定状况而有所差异,但原则上都应该遵从事务域与技能域别离的中心理念

作者:京东科技 倪新明

内容来历:京东云开发者社区