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

本文涉及的产品
MSE Nacos/ZooKeeper 企业版试用,1600元额度,限量50份
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
任务调度 XXL-JOB 版免费试用,400 元额度,开发版规格
简介: 微服务架构:从事务脚本到领域模型

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纯粹主义者之外,还有一个被众人(包括我在内)忽略的基本元素:聚合。事实证明,在开发微服务时,聚合是一个非常有用的概念。在下一部分,我们来看一看,聚合如何解决经典面向对象设计的一些微妙问题。





相关文章
|
2月前
|
存储 BI Shell
Doris基础-架构、数据模型、数据划分
Apache Doris 是一款高性能、实时分析型数据库,基于MPP架构,支持高并发查询与复杂分析。其前身是百度的Palo项目,现为Apache顶级项目。Doris适用于报表分析、数据仓库构建、日志检索等场景,具备存算一体与存算分离两种架构,灵活适应不同业务需求。它提供主键、明细和聚合三种数据模型,便于高效处理更新、存储与统计汇总操作,广泛应用于大数据分析领域。
303 2
|
4月前
|
人工智能 负载均衡 API
长连接网关技术专题(十二):大模型时代多模型AI网关的架构设计与实现
随着 AI 技术快速发展,业务对 AI 能力的渴求日益增长。当 AI 服务面对处理大规模请求和高并发流量时,AI 网关从中扮演着至关重要的角色。AI 服务通常涉及大量的计算任务和设备资源占用,此时需要一个 AI 网关负责协调这些请求来确保系统的稳定性与高效性。因此,与传统微服务架构类似,我们将相关 API 管理的功能(如流量控制、用户鉴权、配额计费、负载均衡、API 路由等)集中放置在 AI 网关层,可以降低系统整体复杂度并提升可维护性。 本文要分享的是B站在大模型时代基于多模型AI的网关架构设计和实践总结,希望能带给你启发。
279 4
|
4月前
|
人工智能 缓存 自然语言处理
Bolt DIY架构揭秘:从模型初始化到响应生成的技术之旅
在使用Bolt DIY或类似的AI对话应用时,你是否曾好奇过从输入提示词到获得回答的整个过程是如何运作的?当你点击发送按钮那一刻,背后究竟发生了什么?本文将揭开这一过程的神秘面纱,深入浅出地解析AI对话系统的核心技术架构。
|
5月前
|
机器学习/深度学习 人工智能 文件存储
Llama Nemotron:英伟达开源基于Llama架构优化的推理模型,253B参数持平DeepSeek R1!
NVIDIA推出的Llama Nemotron系列推理模型,基于Llama架构优化,包含Nano/Super/Ultra三款,在数学推理、编程和工具调用等任务中展现卓越性能。
146 5
Llama Nemotron:英伟达开源基于Llama架构优化的推理模型,253B参数持平DeepSeek R1!
|
5月前
|
人工智能 算法 网络安全
基于PAI+专属网关+私网连接:构建全链路Deepseek云上私有化部署与模型调用架构
本文介绍了阿里云通过PAI+专属网关+私网连接方案,帮助企业实现DeepSeek-R1模型的私有化部署。方案解决了算力成本高、资源紧张、部署复杂和数据安全等问题,支持全链路零公网暴露及全球低延迟算力网络,最终实现技术可控、成本优化与安全可靠的AI部署路径,满足企业全球化业务需求。
|
6月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——常见问题总结
本文总结了Spring Boot中使用事务的常见问题,虽然通过`@Transactional`注解可以轻松实现事务管理,但在实际项目中仍有许多潜在坑点。文章详细分析了三个典型问题:1) 异常未被捕获导致事务未回滚,需明确指定`rollbackFor`属性;2) 异常被try-catch“吃掉”,应避免在事务方法中直接处理异常;3) 事务范围与锁范围不一致引发并发问题,建议调整锁策略以覆盖事务范围。这些问题看似简单,但一旦发生,排查难度较大,因此开发时需格外留意。最后,文章提供了课程源代码下载地址,供读者实践参考。
117 0
|
6月前
|
Java 关系型数据库 数据库
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——Spring Boot 事务配置
本文介绍了 Spring Boot 中的事务配置与使用方法。首先需要导入 MySQL 依赖,Spring Boot 会自动注入 `DataSourceTransactionManager`,无需额外配置即可通过 `@Transactional` 注解实现事务管理。接着通过创建一个用户插入功能的示例,展示了如何在 Service 层手动抛出异常以测试事务回滚机制。测试结果表明,数据库中未新增记录,证明事务已成功回滚。此过程简单高效,适合日常开发需求。
777 0
|
6月前
|
Java 数据库 微服务
微服务——SpringBoot使用归纳——Spring Boot事务配置管理——事务相关
本文介绍Spring Boot事务配置管理,阐述事务在企业应用开发中的重要性。事务确保数据操作可靠,任一异常均可回滚至初始状态,如转账、购票等场景需全流程执行成功才算完成。同时,事务管理在Spring Boot的service层广泛应用,但根据实际需求也可能存在无需事务的情况,例如独立数据插入操作。
110 0
|
4月前
|
机器学习/深度学习 人工智能 算法
大型多模态推理模型技术演进综述:从模块化架构到原生推理能力的综合分析
该研究系统梳理了大型多模态推理模型(LMRMs)的技术发展,从早期模块化架构到统一的语言中心框架,提出原生LMRMs(N-LMRMs)的前沿概念。论文划分三个技术演进阶段及一个前瞻性范式,深入探讨关键挑战与评估基准,为构建复杂动态环境中的稳健AI系统提供理论框架。未来方向聚焦全模态泛化、深度推理与智能体行为,推动跨模态融合与自主交互能力的发展。
248 13
大型多模态推理模型技术演进综述:从模块化架构到原生推理能力的综合分析
|
5月前
|
人工智能 JavaScript 开发工具
MCP详解:背景、架构与应用
模型上下文协议(MCP)是由Anthropic提出的开源标准,旨在解决大语言模型与外部数据源和工具集成的难题。作为AI领域的“USB-C接口”,MCP通过标准化、双向通信通道连接模型与外部服务,支持资源访问、工具调用及提示模板交互。其架构基于客户端-服务器模型,提供Python、TypeScript等多语言SDK,方便开发者快速构建服务。MCP已广泛应用于文件系统、数据库、网页浏览等领域,并被阿里云百炼平台引入,助力快速搭建智能助手。未来,MCP有望成为连接大模型与现实世界的通用标准,推动AI生态繁荣发展。
4361 66