微服务架构谈(4):领域事件-解耦微服务的关键

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 微服务架构谈(4):领域事件-解耦微服务的关键

在领域建模时,我们发现除了命令和操作等业务行为以外,还有一类非常重要的事件。这类事件发生后通常会触发进一步的业务操作,在DDD中这类事件被称为领域事件(Domain Event)。


那到底什么是领域事件?领域事件驱动设计的技术实现机制是怎样的?我们这一章将重点讲解这两个问题。


1 领域事件

领域事件是领域模型非常重要的一部分,用于表示领域中发生的事件。一个领域事件往往会导致进一步的业务操作,它在实现领域模型解耦的同时,还有助于形成完整的业务操作闭环。

举例来说,领域事件可以是业务流程的一个步骤,比如投保业务缴费完成后,触发投保单转保单的动作;也可以是定时批处理过程中发生的事件,比如批处理生成季缴保费通知单,触发缴费邮件通知操作;还可以是一个事件发生后触发的后续动作,比如密码连续输错三次,触发锁定账户的动作。


那在领域建模时,如何识别和捕捉这些领域事件呢?

在用户旅程或者场景分析时,我们需要捕捉业务人员、需求分析人员以及领域专家口中的这些具有前后动作关系的关键词,比如:“如果发生⋯⋯,则⋯⋯”“当做完⋯⋯时,请通知⋯⋯”“发生⋯⋯时,则⋯⋯”等。在这些业务场景中,如果发生某种事件后,会触发进一步的业务操作,那么这个事件很可能就是领域事件。

领域事件采用事件驱动架构(Event-Driven Architecture,EDA)设计,可以切断领域模型之间的强依赖关系,在领域事件发布后,事件发布方不必关心订阅方的事件处理是否成功。这样就可以实现领域模型的解耦,维护领域模型的独立性。当领域模型映射到微服务时,领域事件就可以解耦微服务,这时微服务之间的数据就可以不再要求强一致性,而是基于最终一致性。


再回到具体的业务场景,我们发现有的领域事件发生在微服务内的聚合之间,有的发生在微服务之间,还有两者皆有的场景。一般来说,跨微服务的领域事件会相对较多。在微服务设计时,不同场景下的领域事件的处理方式会不同。

与采用同步服务调用实现数据强一致性的机制不同,领域事件一般都会结合消息中间件和事件发布订阅的异步处理方式,实现数据最终一致性。

那么,领域事件处理为什么要采用最终一致性,而不是强一致性呢?


我们先一起回顾一下第8章的内容,聚合有一个重要设计原则:“在边界之外使用最终一致性。”如果在一次事务提交中,修改的数据超出了一个聚合的边界,简单点说就是一笔交易,如果同时涉及多个聚合的数据更新,那么就可以采用数据最终一致性。


1.1 微服务内的领域事件

在微服务内发生领域事件,如果同时更新多个聚合数据时,你需要确保多个聚合数据的一致性。按照DDD“一次事务只更新一个聚合”的原则,你可以引入事件总线(Event Bus),通过事件总线来实现微服务内多聚合数据的最终一致性,或者采用事务机制保证数据强一致性。

在采用事件总线进行领域事件处理时,可以根据需要完成领域事件实体的构建和事件数据持久化,然后发布方聚合会将领域事件数据发布到事件总线,由订阅方聚合接收领域事件数据后完成后续业务处理。事件总线的设计方式,可能会增加微服务开发的复杂度,需要结合应用的复杂度和收益进行综合考虑。

你可能会问,在同一个微服务内,为什么一次事务更新多个聚合数据时,要用事件总线或事务机制呢?


这是因为聚合是微服务内最小的业务功能单元。为了保证聚合内数据更新时符合聚合内固定的业务规则,在一次事务提交时通常会将聚合内所有变更的对象数据作为整体,通过聚合领域服务或聚合根方法一次通过仓储完成数据持久化操作。如果在一次交易中需要同时更新多个聚合数据,那么每一个聚合就是一个独立的数据提交单元,我们需要确保多个聚合数据都能在这个交易中成功提交并更新,以保证不同聚合数据的一致性。而基于事件总线的异步化机制,就可以保证微服务内聚合之间数据提交时的最终一致性。


如果不采用事件总线的最终数据一致性机制,其实你也可以采用事务机制保证数据强一致性。比如在应用服务中增加事务控制,在对多个聚合的领域服务进行组合和编排时,通过事务机制来确保多个聚合在提交数据时实现数据强一致性。这种方式一般应用于实时性和数据一致性要求高的业务场景,但采用事务机制可能会出现系统性能损耗。


1.2 微服务之间的领域事件

跨微服务的领域事件可以在不同限界上下文,或领域模型之间实现业务协作,其主要目的是实现微服务解耦,推动业务流程或者数据在不同子域或微服务之间流转。同时也可以减轻微服务之间同步服务访问的压力,避免当某个关键微服务无法提供服务时,出现雪崩效应。


领域事件发生在微服务之间的场景比较多,事件处理的机制也更加复杂。微服务之间的领域事件可以采用异步化的最终一致性设计。设计时要总体考虑领域事件的构建、发布和订阅、领域事件数据的持久化、消息中间件,甚至在事件数据持久化时可能还需要引入分布式事务等机制。


微服务之间的领域事件,也可以采用同步服务调用的强一致性设计,实现实时的数据和服务访问。其弊端就是需要引入分布式事务机制,以确保微服务之间的数据强一致性。但分布式事务机制会影响系统性能,同时增加微服务之间的耦合。

所以,应尽量减少微服务之间的同步服务调用方式,优先采用基于消息中间件的最终一致性设计。


2 领域事件案例

下面介绍一个与保险承保业务有关的领域事件的案例,以加深对领域事件的理解。

一个保单的生成,通常会经历很多业务子域、业务状态变更和跨微服务业务数据的传递。这个过程会产生很多领域事件,这些领域事件促成了保险业务数据、对象在不同的微服务和子域之间的流转和角色转换,如不同微服务或聚合之间的实体与值对象之间的转换。在图9-1中,我列出了几个关键流程,用来说明如何用领域事件驱动设计来驱动保险业务流程。


事件起点:客户购买保险,业务人员完成投保单录入,生成投保单,启动缴费动作。


1)投保微服务生成缴费通知单,发布第一个事件:缴费通知单已生成。将缴费通知单事件数据发布到消息中间件。收款微服务订阅缴费通知单事件,完成缴费操作。缴费通知单已生成领域事件结束。


2)收款微服务缴费完成后,发布第二个领域事件:缴费已完成。将缴费事件数据发布到消息中间件。原来的事件订阅方收款微服务这时则变成了事件发布方。原来的发布方投保微服务这时转换为缴费已完成事件的订阅方。投保微服务在收到缴费信息并确认缴费完成后,完成投保单转成保单的操作。缴费已完成领域事件结束。


3)投保微服务在投保单转保单完成后,发布第三个领域事件:保单已生成。将保单事件数据发布到消息中间件。保单微服务接收到保单数据后,完成保单数据保存操作。保单已生成领域事件结束。


4)保单微服务完成保单数据保存后,后面还会发生一系列的领域事件,以并发的方式将保单事件数据通过消息中间件分别发送到佣金、收付和再保等微服务,一直到财务,完成保单后续所有业务流程。这里就不详细展开了。



image.png


图1 保险承保过程中的领域事件分析


综上,通过领域事件驱动的异步化机制,可以推动业务流程和数据在各个不同业务领域和微服务之间的流转,实现领域模型和微服务的解耦,减轻微服务之间服务调用的压力,提升用户体验。

相关文章
|
1天前
|
监控 API 持续交付
构建高效可靠的微服务架构:策略与实践
【5月更文挑战第8天】在当今快速演进的软件开发领域,微服务架构已经成为实现敏捷开发、持续交付和系统弹性的关键模式。本文将探讨构建一个高效且可靠的微服务系统所必须的策略和最佳实践。我们将从服务的划分与设计原则出发,讨论如何通过容器化、服务发现、API网关以及断路器模式来优化系统的可伸缩性和鲁棒性。此外,我们还将涉及监控、日志管理以及CI/CD流程在确保微服务架构稳定运行中的作用。
|
1天前
|
消息中间件 Java 微服务
Java微服务架构实践指南
Java微服务架构实践指南
10 0
|
1天前
|
Kubernetes 持续交付 开发者
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第8天】 随着现代软件开发的不断演进,微服务架构已成为众多企业解决复杂系统问题的首选方案。本文深入探讨了微服务架构的核心概念、设计原则以及实施策略,旨在为后端开发者提供一种清晰、高效的技术路径。通过分析微服务的优势与挑战,结合具体的应用实例,文章将展示如何通过容器化、服务网格和持续集成/持续部署(CI/CD)等先进技术手段,实现后端服务的高可用性、可扩展性和敏捷性。
|
1天前
|
消息中间件 监控 Java
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第8天】随着现代软件开发的复杂性日益增加,传统的单体应用架构逐渐难以满足快速迭代和灵活部署的需求。微服务架构作为一种新的解决方案,以其模块化、独立性强和易于扩展的特点,正在成为后端开发领域的重要趋势。本文将深入探讨如何构建一个高效的微服务架构,并分析其对后端开发实践的影响。
|
1天前
|
敏捷开发 持续交付 API
构建高效微服务架构:后端开发的现代实践
【5月更文挑战第8天】 在数字化转型的浪潮中,微服务架构已成为企业追求敏捷开发、持续交付和系统弹性的关键解决方案。本文将深入探讨微服务的核心概念,包括其设计原则、优缺点以及如何在后端开发中实现高效的微服务架构。我们将通过实际案例分析,展示微服务如何帮助企业快速适应市场变化,同时保持系统的可维护性和扩展性。
|
1天前
|
API 持续交付 开发者
构建高效微服务架构:后端开发的新视角
【5月更文挑战第8天】 随着现代软件开发的演变,微服务架构已经成为了企业追求敏捷、可扩展和灵活部署的重要解决方案。本文将深入探讨如何构建一个高效的微服务架构,包括关键的设计原则、技术栈选择以及持续集成与部署的最佳实践。我们还将讨论微服务带来的挑战,如数据一致性、服务发现和网络延迟,并提出相应的解决策略。通过本文,后端开发者将获得构建和维护微服务系统所需的深度知识,并了解如何在不断变化的技术环境中保持系统的健壮性和可维护性。
28 8
|
1天前
|
负载均衡 网络协议 应用服务中间件
理解现代微服务架构中的服务发现
微服务架构已经成为软件开发领域中的一股重要力量。在这种架构中,服务发现是关键的一环。本文旨在详细探讨服务发现的概念、其在微服务中的重要性,以及实现服务发现的常见方法和工具。
|
2天前
|
设计模式 Kubernetes 数据库
构建高效可靠的微服务架构:后端开发的新范式
【5月更文挑战第7天】在现代软件开发的浪潮中,微服务架构已经成为一种流行的设计模式。它通过将应用程序分解为一组小的、独立的服务来提高系统的可维护性和扩展性。本文深入探讨了微服务架构的核心概念、优势以及如何利用最新的后端技术构建一个高效且可靠的微服务体系。我们将讨论关键的设计原则,包括服务的独立性、通信机制、数据一致性和容错性,并展示如何在云环境中部署和管理这些服务。
16 3
|
3天前
|
监控 负载均衡 数据安全/隐私保护
探索微服务架构下的服务网格(Service Mesh)实践
【5月更文挑战第6天】 在现代软件工程的复杂多变的开发环境中,微服务架构已成为构建、部署和扩展应用的一种流行方式。随着微服务架构的普及,服务网格(Service Mesh)作为一种新兴技术范式,旨在提供一种透明且高效的方式来管理微服务间的通讯。本文将深入探讨服务网格的核心概念、它在微服务架构中的作用以及如何在实际项目中落地实施服务网格。通过剖析服务网格的关键组件及其与现有系统的协同工作方式,我们揭示了服务网格提高系统可观察性、安全性和可操作性的内在机制。此外,文章还将分享一些实践中的挑战和应对策略,为开发者和企业决策者提供实用的参考。
|
3天前
|
缓存 监控 数据库
构建高性能微服务架构:后端开发的终极指南
【5月更文挑战第6天】 在现代软件开发的浪潮中,微服务架构以其灵活性、可扩展性和容错性引领着技术潮流。本文深入探索了构建高性能微服务架构的关键要素,从服务划分原则到通信机制,再到持续集成和部署策略。我们将透过实战案例,揭示如何优化数据库设计、缓存策略及服务监控,以确保系统的稳定性和高效运行。文中不仅分享了最佳实践,还讨论了常见的陷阱与解决之道,为后端开发者提供了一条清晰、可行的技术路径。