将领域驱动设计原则应用于微服务架构
在这篇文章中,我们将学习领域驱动设计的基础知识,以及如何将其应用于微服务。微服务是开发软件的最可扩展的方式。
微服务是开发软件的最可扩展的方式。但你需要一个好的设计,让开发人员团队自主工作,并在不踩到对方脚趾的情况下进行部署;否则,你就会失去大部分的可扩展性优势。
领域驱动开发允许我们通过将大系统分解为独立的单元来规划微服务架构,了解每个单元的职责,并确定它们的关系。在这篇文章中,我们将学习领域驱动设计的基础知识,以及如何将其应用于微服务。
什么是领域驱动设计?
领域驱动设计(DDD)是一种软件设计方法,开发人员通过构建模型来理解一个领域的业务需求。这些模型作为开发软件的概念基础。
根据《领域驱动设计》一书的作者Eric Evans的说法 《应对软件核心的复杂性 》一书的作者,领域是:
一个知识、影响或活动的范围。用户应用一个程序的主题领域就是软件的领域。
一个人能够多好地解决一个问题,取决于他对领域的理解能力。开发人员是聪明人,但他们不可能成为所有领域的专家。他们需要与领域专家合作,以保证代码与业务规则和客户需求相一致。
开发人员和领域专家使用统一的语言来分享知识、文档、计划和代码。
微服务架构的两个最重要的DDD概念是有界上下文和上下文地图。
有界上下文(BC)
一个词出现的环境决定了它的含义。根据不同的语境,"书 "可能指的是一篇书面作品,也可能是指 "预订房间"。A 有界上下文 (BC)是一个术语具有明确和毫不含糊的含义的空间。
在DDD之前,通常的做法是试图找到一个横跨完整领域的模型。问题是,领域越大,就越难找到一致和统一的模型。DDD的解决方案是确定BC,以便将领域分解为可管理的子域。
书 "的相关属性会随着上下文的变化而变化
在软件中,我们需要精确。这就是为什么定义BC很关键:它给我们提供了一个精确的词汇,称为 无处不在的语言,可以在开发人员和领域专家之间的对话中使用。这种无处不在的语言存在于整个设计过程、项目文档和代码中。
语境地图
BC的存在预示着对沟通渠道的需求。例如,如果我们在电子商务领域工作,销售人员应该在销售产品之前与库存进行核对。而一旦售出,就应该由运输部门来确保将产品运送到正确的地址。在DDD中,这些关系被描述为 语境图.
有边界的上下文通信被用来实现一个高层次的任务。
微服务的领域驱动设计
DDD分两个阶段进行:
-
在战略阶段, 我们确定BC,并在上下文地图中把它们映射出来。
-
在战术阶段, 我们根据子域的业务规则为每个BC建模。
让我们看看每个阶段在微服务架构设计中是如何发挥作用的。
战略阶段
在这个阶段,我们邀请开发人员、领域专家、产品所有者和业务分析师进行头脑风暴,分享知识并制定初步计划。在主持人的帮助下,这可以采取 "事件风暴 "研讨会的形式,我们从领域中的重大事件出发,建立模型并确定业务需求。
在 "事件风暴 "会议中,领域事件被用作分享知识和识别业务需求的催化剂。
在战略DDD中,我们采取一种高层次的、从上到下的设计方法。我们首先分析领域,以确定其业务规则。由此,我们推导出一个BC列表。
战略领域驱动设计帮助我们确定各个微服务的逻辑边界。
这些边界作为天然的屏障,保护着里面的模型。因此,每个BC都代表了实现至少一个微服务的机会。
接下来,我们必须决定BC将如何进行通信。Eric Evans列出了七种类型的关系,而其他作者列出了其中的六种。无论我们如何计算,至少有三种(共享内核、客户/供应商和顺应者)意味着紧耦合,这在微服务设计中是我们不希望看到的,可以忽略。这就给我们留下了四种类型的关系:
-
开放主机服务(OHS):服务提供者定义了一个开放的协议供其他人消费。这是一种开放式的关系,因为要由消费者来遵守协议。
-
发布的语言(PL):这种关系使用一种知名的语言,如XML、JSON、GraphQL或任何其他适合该领域的语言。这种类型的关系可以与OHS结合。
-
反腐败层(ACL):这是一种服务消费者的防御机制。反腐败层是一个在下游服务前面实现的抽象和翻译包装层。当上游的东西发生变化时,消费者服务只需要更新ACL。
-
分开的方式:当进一步分析后发现两个服务之间的整合没有什么价值时,就会发生这种情况。这与关系相反--它意味着BC没有联系,不需要交互。
在战略DDD分析的最后,我们得到了一张详细描述BC及其关系的上下文图。
ACL在下游实施,以减轻上游变化的影响。OHS的作用正好相反。它在上游实施,为下游的服务提供一个稳定的接口。
战术阶段
在这个阶段,我们深入研究子领域并创建模型。
领域驱动设计是迭代的
虽然看起来我们必须先对领域进行详尽的描述,然后才能开始编写代码,但现实是,DDD和所有的软件设计一样,是一个迭代的过程。
在纸面上,有界的上下文和上下文地图可能看起来还不错,但在实施时,它们可能会转化为太大的服务,不能正确地称为微服务。反过来说,职责重叠的聊天型微服务可能需要合并成一个。
随着开发的进展,你对该领域有了更好的理解,你将能够做出更好的判断,增强模型,并进行更有效的沟通。
设计微服务的更多方法
毫无疑问,DDD是一种重理论的设计模式。因此,只有当正在开发的系统足够复杂,值得进行额外的规划工作时,才推荐使用这种方法。
其他方法,如测试驱动开发(TDD)或行为驱动开发 (BDD),对于较小、较简单的系统来说可能已经足够。TDD是开始时最快的方法,在处理单个微服务或甚至只由几个服务组成的应用时效果最好。
在更大的范围内,我们可以使用BDD,它迫使我们用集成和验收测试来验证批发行为。如果你从事低到中等复杂度的设计,BDD可能会很有效,但一旦你达到一定的门槛,维护测试就会拖慢你的速度。
你也可以将这三种模式结合起来,为每个开发阶段选择最佳模式。比如说:
-
用战略DDD识别微服务和它们的关系。
-
用战术性DDD对每个微服务进行建模。
-
由于每个团队都是自主的,他们可以选择采用BDD或TDD(或两者的混合)来开发一个微服务或一个微服务集群。
DDD的学习和实施可能让人感到畏惧,但它对于开发微服务架构的价值是非常值得的。