如何构建基于 DDD 领域驱动的微服务?(1)

本文涉及的产品
注册配置 MSE Nacos/ZooKeeper,118元/月
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 如何构建基于 DDD 领域驱动的微服务?

尽管微服务中的“微”一词表示服务的规模,但它并不是使用微服务的唯一标准。当团队转向基于微服务的架构时,他们旨在提高敏捷性以及自主且频繁地部署功能。很难确定这种架构风格的简单定义。我喜欢Adrian Cockcroft的关于微服务的简短定义: “ 面向服务的体系结构,它由松散耦合的、具有上下文边界的元素组成。”


尽管这定义了高级设计启发式技术,但微服务架构具有一些独特的特性,使其有别于以往的面向服务的架构。以下是其中一些特征。这些以及其他一些文档都有据可查-Martin Fowler的文章和Sam Newman的Building Microservices,仅举几例。


  • 服务具有围绕业务上下文而不是任意技术上抽象的明确定义的边界
  • 通过意图公开界面隐藏实现细节并公开功能
  • 服务不会共享超出其边界的内部结构。例如,不共享数据库。
  • 服务可以抵抗故障。
  • 团队独立拥有职能,并能够自主发布变更
  • 团队拥护自动化文化。例如,自动化测试,持续集成和持续交付


简而言之,我们可以将这种体系结构样式总结如下:


松耦合的面向服务的体系结构,其中每个服务都包含在定义明确的有界上下文中,从而可以快速,频繁且可靠地交付应用程序。


领域驱动设计和有界上下文


微服务的力量来自明确定义其职责并划分它们之间的边界。此处的目的是在边界内建立高凝聚力,并在边界外建立低耦合(banq注:高凝聚低耦合)。也就是说,趋于一起改变的事物应该属于同一事物。就像在许多现实生活中的问题一样,这说起来容易做起来难,业务在不断发展,逻辑的假设前提也会随之改变。因此,重构的能力是设计系统时要考虑的另一关键问题。


领域驱动设计(DDD)是关键,在我们看来,这是设计微服务时必不可少的工具,无论是打破整体还是实施未开发项目。领域驱动的设计(Eric Evans在他的书中提出)是一组思想、原理和模式,可帮助基于业务领域的基础模型设计软件系统。开发人员和领域专家共同合作,以通用的通用语言创建业务模型。然后,他们将这些模型绑定到有意义的系统,并在这些系统与从事这些服务的团队之间建立协作协议。更重要的是,他们设计了系统之间的概念轮廓或边界。


微服务设计从这些概念中汲取了灵感,因为所有这些原理都有助于构建可以相互独立变化和发展的模块化系统。


在继续进行之前,让我们快速了解一下DDD的一些基本术语。域驱动设计的完整概述超出了本博客的范围。我们强烈建议任何尝试构建微服务的人推荐Eric Evans的书籍。


领域:代表组织的工作。例如它是零售或电子商务。


子域:组织或组织内的业务部门。域由多个子域组成。


无所不在的语言:这是用于表达模型的语言。在下面的示例中,Item是一个模型,属于这些子域中每个子域的通用语言。开发人员,产品经理,领域专家和业务涉众都同意使用相同的语言,并在其工件(代码,产品文档等)中使用该语言。


有界上下文:域驱动的设计将有界上下文定义为“单词或语句能确定其含义的设置”。简而言之,这意味着模型是有意义的边界。在上面的示例中,“项目”在每种上下文中的含义不同。在目录上下文中,项目表示可售产品,而在购物车上下文中,则表示客户已将其添加到购物车中的项目。在“运输”上下文中,它表示将要运送给客户的仓库物料。这些模型中的每一个都是不同的,并且每个都有不同的含义,并且可能包含不同的属性。通过将这些模型分离并隔离在它们各自的边界内,我们可以自由地表达模型而没有歧义。


注意:必须了解子域和有界上下文之间的区别。子域属于问题空间,即您的企业如何看待问题,而受限上下文属于解决方案空间,即我们将如何实施问题的解决方案。从理论上讲,每个子域可能具有多个有界上下文,尽管我们努力为每个子域提供一个有界上下文。


微服务与有限上下文如何相关


现在,微服务在哪里适合?可以说每个有界上下文都映射到微服务吗?是的,我们将明白为什么。在某些情况下,有界上下文的边界或轮廓可能很大。


image.png


考虑上面的例子。定价绑定上下文具有三个不同的模型-价格,定价项目和折扣,每个模型负责目录项目的价格,计算项目列表的总价格并分别应用折扣。我们可以创建一个包含以上所有模型的系统,但是它可能会成为一个不合理的大型应用程序。如前所述,每个数据模型都有其不变性和业务规则。随着时间的流逝,如果我们不小心的话,系统可能会变成一个泥泞的大球,边界模糊,职责重叠,甚至可能回到我们开始的地方—一个整体。


对系统进行建模的另一种方法是将相关模型分离或分组为单独的微服务。在DDD中,这些模型(价格,定价项目和折扣)被称为聚合Aggregates。聚合是组成相关模型的独立模型。您只能通过已发布的界面更改聚合的状态,并且聚合可确保一致性,并且不变量保持良好状态。


聚合是关联对象的集群,被视为数据更改的单元。外部引用仅限于AGGREGATE的一个成员,称为根。一组一致性规则适用于AGGREGATE的边界。


image.png


同样,没有必要一定要将每个聚合建模为一个独特的微服务。图中的服务(聚合)是一对一关系,但这不一定是规则。在某些情况下,在单个服务中托管多个聚合可能是有意义的,尤其是当我们不完全了解业务领域时。需要注意的重要一点是,只能在单个聚合中保证一致性,并且只能通过已发布的界面修改聚合。任何违反这些规定的行为都有变成大泥球的风险。


上下文映射—精确划分微服务边界的一种方法


整体结构通常由不同的模型组成,大多数模型是紧密耦合的-模型可能知道彼此的亲密细节,更改一个模型可能会对另一个模型产生副作用,依此类推。分解整体时,确定这些模型(在这种情况下为集合)及其关系至关重要。上下文映射可以帮助我们做到这一点。它们用于标识和定义各种有界上下文和聚合之间的关系。在上面的示例中,有界上下文定义了模型的边界(价格,折扣等),而上下文映射定义了这些模型之间以及不同有界上下文之间的关系。


上下文映射的完整探索不在本博客的讨论范围之内,但我们将通过一个示例进行说明。下图显示了处理电子商务订单付款的各种应用程序。


购物车上下文负责订单的在线授权;订单上下文流程过帐付款后的付款流程;联络中心会处理所有例外情况,例如重试付款和更改用于订单的付款方式

为了简单起见,让我们假设所有这些上下文都是作为单独的服务实现的

所有这些上下文封装了相同的模型。

请注意,这些模型在逻辑上是相同的。也就是说,它们都遵循相同的通用域语言-付款方式,授权和结算。只是它们是不同上下文的一部分。

重新定义服务边界—将聚合映射到正确的上下文


错误案例如下图:


image.png


电子商务中所有模型都直接与单个支付聚合的网关上下文(payment gateway context)集成,支付需要保证事务性,但是由于与多个服务集成,支付的事务性就不能通过在各种服务之间强制执行不变性和一致性来实现,(banq注:当然有人就提出分布式事务的概念来在这些不同服务之间实现支付过程的事务性,这其实是在错误设计基础上的伪概念)。


请注意,支付网关中的任何更改都将迫使更改多个服务,并可能更改多个团队,因为不同的组可以拥有这些上下文。


进行一些调整并使聚合与正确的上下文对齐,我们可以更好地表示这些子域如下图。发生了很多变化。让我们回顾一下更改:


image.png


通常,整体(单体)或遗留应用程序具有许多聚合,通常具有重叠的边界。创建这些聚合及其依赖关系的上下文地图有助于我们了解将要从这些整体中摆脱出来的任何新微服务的轮廓。请记住,微服务架构的成功或失败取决于聚合之间的低耦合以及这些聚合之间的高内聚性。


同样重要的是要注意,有界上下文本身就是合适的内聚单元。即使上下文具有多个聚合,整个上下文及其聚合也可以组成一个微服务。我们发现这种启发式方法对于有些晦涩的领域特别有用-考虑组织正在涉足的新业务领域。您可能对分离的正确边界没有足够的了解,并且聚集体的任何过早分解都可能导致昂贵的重构。想象一下,由于数据迁移,不得不将两个数据库合并为一个,因为我们偶然发现两个聚合属于同一类。但是请确保通过接口将这些聚合充分隔离,以使它们不知道彼此的复杂细节。



相关文章
|
5天前
|
运维 Kubernetes Docker
利用Docker和Kubernetes构建微服务架构
利用Docker和Kubernetes构建微服务架构
|
12天前
|
运维 持续交付 API
从零构建微服务架构:一次深度技术探索之旅####
【10月更文挑战第28天】 本文记录了作者在从零开始构建微服务架构过程中的深刻技术感悟,通过实战案例详细剖析了微服务设计、开发、部署及运维中的关键要点与挑战。文章首先概述了微服务架构的核心理念及其对企业IT架构转型的重要性,随后深入探讨了服务拆分策略、API网关选型、服务间通信协议选择、容器化部署(Docker+Kubernetes)、以及持续集成/持续部署(CI/CD)流程的设计与优化。最后,分享了在高并发场景下的性能调优经验与故障排查心得,旨在为读者提供一套可借鉴的微服务架构实施路径。 ####
49 3
|
19天前
|
监控 API 持续交付
构建高效后端服务:微服务架构的深度探索
【10月更文挑战第20天】 在数字化时代,后端服务的构建对于支撑复杂的业务逻辑和海量数据处理至关重要。本文深入探讨了微服务架构的核心理念、实施策略以及面临的挑战,旨在为开发者提供一套构建高效、可扩展后端服务的方法论。通过案例分析,揭示微服务如何帮助企业应对快速变化的业务需求,同时保持系统的稳定性和灵活性。
46 9
|
19天前
|
Kubernetes 负载均衡 Docker
构建高效微服务架构:Docker与Kubernetes的完美搭档
【10月更文挑战第22天】随着云计算和容器技术的快速发展,微服务架构逐渐成为现代企业级应用的首选架构。微服务架构将一个大型应用程序拆分为多个小型、独立的服务,每个服务负责完成一个特定的功能。这种架构具有灵活性、可扩展性和易于维护的特点。在构建微服务架构时,Docker和Kubernetes是两个不可或缺的工具,它们可以完美搭档,为微服务架构提供高效的支持。本文将从三个方面探讨Docker和Kubernetes在构建高效微服务架构中的应用:一是Docker和Kubernetes的基本概念;二是它们在微服务架构中的作用;三是通过实例讲解如何使用Docker和Kubernetes构建微服务架构。
53 6
|
19天前
|
Kubernetes 监控 数据中心
容器化与微服务:构建高效开发环境的双剑合璧
【10月更文挑战第20天】本文探讨了容器化技术(如Docker和Kubernetes)与微服务架构的结合,如何共同构建高效、灵活的开发环境。容器化解决了环境一致性、快速部署和资源隔离的问题,而微服务架构则提升了系统的可维护性和可扩展性。通过容器编排工具、CI/CD流程和服务网格,两者的结合进一步优化了开发和运维效率。文章还分享了实施这两项技术的最佳实践和职业心得。
|
6天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
34 6
|
6天前
|
设计模式 Java API
微服务架构演变与架构设计深度解析
【11月更文挑战第14天】在当今的IT行业中,微服务架构已经成为构建大型、复杂系统的重要范式。本文将从微服务架构的背景、业务场景、功能点、底层原理、实战、设计模式等多个方面进行深度解析,并结合京东电商的案例,探讨微服务架构在实际应用中的实施与效果。
19 1
|
2月前
|
安全 应用服务中间件 API
微服务分布式系统架构之zookeeper与dubbo-2
微服务分布式系统架构之zookeeper与dubbo-2
|
2月前
|
负载均衡 Java 应用服务中间件
微服务分布式系统架构之zookeeper与dubbor-1
微服务分布式系统架构之zookeeper与dubbor-1
|
3月前
|
Kubernetes Cloud Native Docker
云原生之旅:从容器到微服务的架构演变
【8月更文挑战第29天】在数字化时代的浪潮下,云原生技术以其灵活性、可扩展性和弹性管理成为企业数字化转型的关键。本文将通过浅显易懂的语言和生动的比喻,带领读者了解云原生的基本概念,探索容器化技术的奥秘,并深入微服务架构的世界。我们将一起见证代码如何转化为现实中的服务,实现快速迭代和高效部署。无论你是初学者还是有经验的开发者,这篇文章都会为你打开一扇通往云原生世界的大门。