微服务架构:从事务脚本到领域模型

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
云原生网关 MSE Higress,422元/月
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: 微服务架构:从事务脚本到领域模型

image.png


图1 Order Service具有六边形架构。它由业务逻辑和一个或多个与其他服务和外部应用程序连接的适配器组成


图1显示了一个典型的服务架构。业务逻辑是六边形架构的核心。业务逻辑的周围是入站和出站适配器。入站适配器处理来自客户端的请求并调用业务逻辑出站适配器被业务逻辑调用,然后它们再调用其他服务和外部应用程序。


此服务由业务逻辑和以下适配器组成。

  • REST API adapter:入站适配器,实现REST API,这些API会调用业务逻辑。
  • OrderCommandHandlers入站适配器,它接收来自消息通道的命令式消息,并调用业务逻辑。
  • Database Adapter由业务逻辑调用以访问数据库的出站适配器。
  • Domain Event Publishing Adapter将事件发布到消息代理的出站适配器。

业务逻辑通常是服务中最复杂的部分。在开发业务逻辑时,你应该以最适合应用程序的方式,精心地设计和组织业务逻辑。我确信大多数读者都经历过不得不维护别人的糟糕代码的挫败感。大多数企业应用程序都是用面向对象的语言编写的,例如Java,因此它们由类和方法组成。但是使用面向对象的语言并不能保证业务逻辑具有面向对象的设计。在开发业务逻辑时必须做出的关键决策是选用面向对象的方式,还是选用面向过程的方式。组织业务逻辑有两种主要模式:面向过程的事务脚本模式和面向对象的领域建模模式。


1 使用事务脚本模式设计业务逻辑


虽然我一直积极地倡导使用面向对象的方式,但在某些情况下使用面向对象的设计方法会有一种“杀鸡用牛刀”的感觉,例如在开发简单的业务逻辑时。在这种情况下,更好的方法是编写面向过程的代码,并使用Martin Fowler在《Patterns of EnterpriseApplication Architecture》一书中提到的事务脚本模式。你可以编写一个称为事务脚本的方法来处理来自表示层的每个请求,而不是进行任何面向对象的设计。如图2所示,这种方法的一个重要特征是实现行为的类与存储状态的类是分开的。


image.png


图2 将业务逻辑组织为事务脚本。在典型的基于事务脚本的设计中,一组类实现行为,另一组类负责存储状态。事务脚本通常被写成没有状态的类。脚本访问没有行为的数据类以完成持久化的任务

 

使用事务脚本模式时,脚本通常位于服务类中,在此示例中是OrderService类。每个服务类都有一个用于请求或系统操作的方法。这个方法实现该请求的业务逻辑。它使用数据访问对象(DAO)访问数据库,例如OrderDao数据对象(在此示例中为Order类)是纯数据,几乎没有行为。

 



image.png


这种设计风格是高度面向过程的,仅仅依赖于面向对象编程(OOP)语言的少量功能。就好比你使用C或其他非OOP语言编写应用所能实现的功能。然而,在适当的时候,你不应该羞于使用面向过程的设计。这种方法适用于简单的业务逻辑。但这往往不是实现复杂业务逻辑的好方法。



2 使用领域模型模式设计业务逻辑


面向过程方法的可以简单迅速地搞定项目,这非常诱人。你可以专注编写业务逻辑代码,而无须仔细考虑如何设计和组织各种类。但是问题在于,如果业务逻辑变得复杂,你最终可能会得到噩梦般难以维护的代码。实际上,就像单体应用程序不断增长的趋势一样,事务脚本也存在同样的问题。因此,除非是编写一个非常简单的应用程序,否则你应该抵制编写面向过程代码的诱惑,使用领域模型模式,并进行面向对象的设计。



在面向对象的设计中,业务逻辑由对象模型和相对较小的一些类的网络组成。这些类通常直接对应于问题域中的概念。在这样的设计中,有些类只有状态或行为,但很多类同时包含状态和行为,这样的类都是精心设计的。图3显示了领域模型模式的示例。


image.png


图3 将业务逻辑组织为领域模型。大多数业务逻辑由具有状态和行为的类组成


与事务脚本模式一样,OrderService类具有针对每个请求或系统操作的方法。但是在使用领域模型模式时,服务方法通常很简单。因为服务方法几乎总是调用持久化领域对象,这些对象中包含大量的业务逻辑。例如,服务方法可以从数据库加载领域对象并调用其中一个方法。在这个例子中,Order类具有状态和行为。此外,它的状态是私有的,只能通过它的方法间接访问。

使用面向对象设计有许多好处。首先,这样的设计易于理解和维护。它不是由一个完成所有事情的大类组成,而是由许多小类组成,每个小类都有少量职责。此外,诸如Account、BankingTransaction和OverdraftPolicy这些类都密切地反映了现实世界,这使得它们在设计中的角色更容易理解。其次,我们的面向对象设计更容易测试:每个类都可以并且应该能够被独立测试。最后,面向对象的设计更容易扩展,因为它可以使用众所周知的设计模式,例如策略模式(Strategy pattern)和模板方法模式(Template methodpattern),这些设计模式定义了在不修改代码的情况下扩展组件的方法。


领域建模模式看似完美,但这种方法同样也存在许多问题,尤其是在微服务架构中。要解决这些问题,你需要使用称为领域驱动设计的思路来优化面向对象设计。


3 关于领域驱动设计


领域驱动设计Domain-Driven Design,DDD)的概念产生于Eric Evans写的《Domain Driven Design》一书,DDD是对面向对象设计的改进,是开发复杂业务逻辑的一种方法。我在第2章介绍过DDD,领域驱动设计的子域概念有助于把应用程序分解为服务。使用DDD时,每个服务都有自己的领域模型,这就避免了在单个应用程序全局范围内的领域模型问题。子域和相关联的限界上下文的相关概念是两种战略性DDD模式。


DDD还有一些战术性模式,它们是领域模型的基本元素(building block)。每个模式都是一个类在领域模型中扮演的角色,并定义了类的特征。开发人员广泛采用的基本元素包括以下几种。

  • 实体(entity):具有持久化ID的对象。具有相同属性值的两个实体仍然是不同的对象。在Java EE应用程序中,使用JPA @Entity进行持久化的类通常是DDD实体。
  • 值对象(value object):作为值集合的对象。具有相同属性值的两个值对象可以互换使用。值对象的一个例子是Money类,它由币种和金额组成。
  • 工厂(factory):负责实现对象创建逻辑的对象或方法,该逻辑过于复杂,无法由类的构造函数直接完成。它还可以隐藏被实例化的具体类。工厂方法一般可实现为类的静态方法。
  • 存储库(repository):用来访问持久化实体的对象,存储库也封装了访问数据库的底层机制。
  • 服务(service):实现不属于实体或值对象的业务逻辑的对象。

许多开发人员都使用这些基本元素,有些基本元素是通过JPASpring框架等实现的。除了DDD纯粹主义者之外,还有一个被众人(包括我在内)忽略的基本元素:聚合。事实证明,在开发微服务时,聚合是一个非常有用的概念。在下一部分,我们来看一看,聚合如何解决经典面向对象设计的一些微妙问题。





相关文章
|
12天前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
12天前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
113 68
从单体到微服务:如何借助 Spring Cloud 实现架构转型
|
11天前
|
运维 监控 持续交付
微服务架构解析:跨越传统架构的技术革命
微服务架构(Microservices Architecture)是一种软件架构风格,它将一个大型的单体应用拆分为多个小而独立的服务,每个服务都可以独立开发、部署和扩展。
111 36
微服务架构解析:跨越传统架构的技术革命
|
6天前
|
机器学习/深度学习 测试技术 定位技术
新扩散模型OmniGen一统图像生成,架构还高度简化、易用
近期,一篇题为“OmniGen: Unified Image Generation”的论文介绍了一种新型扩散模型OmniGen,旨在统一图像生成任务。OmniGen架构简洁,无需额外模块即可处理多种任务,如文本到图像生成、图像编辑等。该模型通过修正流优化,展现出与现有模型相当或更优的性能,尤其在图像编辑和视觉条件生成方面表现突出。OmniGen仅含3.8亿参数,却能有效处理复杂任务,简化工作流程。尽管如此,OmniGen仍存在对文本提示敏感、文本渲染能力有限等问题,未来研究将继续优化其架构与功能。
35 16
|
14天前
|
设计模式 负载均衡 监控
探索微服务架构下的API网关设计
在微服务的大潮中,API网关如同一座桥梁,连接着服务的提供者与消费者。本文将深入探讨API网关的核心功能、设计原则及实现策略,旨在为读者揭示如何构建一个高效、可靠的API网关。通过分析API网关在微服务架构中的作用和挑战,我们将了解到,一个优秀的API网关不仅要处理服务路由、负载均衡、认证授权等基础问题,还需考虑如何提升系统的可扩展性、安全性和可维护性。文章最后将提供实用的代码示例,帮助读者更好地理解和应用API网关的设计概念。
44 8
|
20天前
|
网络协议 网络架构
TCP/IP协议架构:四层模型详解
在网络通信的世界里,TCP/IP协议栈是构建现代互联网的基础。本文将深入探讨TCP/IP协议涉及的四层架构,以及每一层的关键功能和作用。
93 5
|
20天前
|
机器学习/深度学习 存储 人工智能
【AI系统】模型演进与经典架构
本文探讨了AI计算模式对AI芯片设计的重要性,通过分析经典模型结构设计与演进、模型量化与压缩等核心内容,揭示了神经网络模型的发展现状及优化方向。文章详细介绍了神经网络的基本组件、主流模型结构、以及模型量化和剪枝技术,强调了这些技术在提高模型效率、降低计算和存储需求方面的关键作用。基于此,提出了AI芯片设计应考虑支持神经网络计算逻辑、高维张量存储与计算、灵活的软件配置接口、不同bit位数的计算单元和存储格式等建议,以适应不断发展的AI技术需求。
28 5
|
18天前
|
消息中间件 运维 Kubernetes
后端架构演进:从单体到微服务####
本文将探讨后端架构的演变过程,重点分析从传统的单体架构向现代微服务架构的转变。通过实际案例和理论解析,揭示这一转变背后的技术驱动力、挑战及最佳实践。文章还将讨论在采用微服务架构时需考虑的关键因素,包括服务划分、通信机制、数据管理以及部署策略,旨在为读者提供一个全面的架构转型视角。 ####
31 1
|
21天前
|
弹性计算 运维 开发者
后端架构优化:微服务与容器化的协同进化
在现代软件开发中,后端架构的优化是提高系统性能和可维护性的关键。本文探讨了微服务架构与容器化技术如何相辅相成,共同推动后端系统的高效运行。通过分析两者的优势和挑战,我们提出了一系列最佳实践策略,旨在帮助开发者构建更加灵活、可扩展的后端服务。
|
21天前
|
消息中间件 运维 Cloud Native
云原生架构下的微服务优化策略####
本文深入探讨了云原生环境下微服务架构的优化路径,针对服务拆分、通信效率、资源管理及自动化运维等核心环节提出了具体的优化策略。通过案例分析与最佳实践分享,旨在为开发者提供一套系统性的解决方案,以应对日益复杂的业务需求和快速变化的技术挑战,助力企业在云端实现更高效、更稳定的服务部署与运营。 ####