一种残膜回收机防缠绕挑膜装置的制 一种秧草收获机用电力驱动行走机构

基于领域事件和事件溯源的代码结构优化方法及系统与流程

2022-05-18 04:23:27 来源:中国专利 TAG:


1.本发明涉及数据处理技术领域,具体地说是基于领域事件和事件溯源的代码结构优化方法及系统。


背景技术:

2.在传统j2ee的action/service/dao分层思想模式下,对象只是数据的载体,只有数据字段和get/set方法,没有逻辑在对象中,这种数据模型在领域驱动设计中被称为“贫血模型”。随着项目变复杂了,业务逻辑、状态会散落到在大量方法中,原本的代码意图会渐渐不明确,我们将这种情况称为“贫血模型而引发的失忆症”。
3.为了解决这种问题,可以根据领域驱动设计的思想,降低业务逻辑复杂度,构建“充血模型”与“聚合”,并使用“领域事件”来描述与处理业务模型里的行为。这样可以将处理的流程解耦,实现系统的可扩展性,提高主业务流程的内聚性。
4.如何降低业务逻辑复杂度是需要解决的技术问题。


技术实现要素:

5.本发明的技术任务是针对以上不足,提供基于领域事件和事件溯源的代码结构优化方法及系统,来解决如何降低业务逻辑复杂度的技术问题。
6.第一方面,本发明的基于领域事件和事件溯源的代码结构优化方法,包括如下步骤:
7.在命令的引发下,通过聚合或领域服务创建一个具有唯一标识符的事件,将所述事件包装在一个eventmessage中;
8.基于观察者模式,通过eventbus将事件分发至事件订阅方,所述事件订阅方包括事件存储订阅方、即时转发订阅方以及其他订阅方;
9.对于事件,通过事件存储订阅方将事件转发并存储数据库,通过即时转发订阅方将事件转发至消息队列,通过转发器将数据库中事件转发至消息队列;
10.基于聚合生成的系列事件,通过聚合根重建聚合的状态。
11.作为优选,所述聚合为一组相关对象的集合,作为一个整体被外界访问;
12.所述聚合具有如下原则:具有唯一标识、为小聚合、通过唯一标识引用其它聚合、在聚合边界之外使用最终一致性,所述小聚合理解为作为集合其对象数量小于阈值。
13.作为优选,所述事件包装在一个eventmessage中,所述eventmessage中包括用于标识事件的标识符、用于标识事件来源的消息类型、事件元数据、有效载荷以及时间戳。
14.作为优选,在java项目中,对于命令使用@commandhandler注解,通过反射把注解的方法保存在内存中,将命令名作为key,将被注解的方法作为value,当命令总线接受的命令时,在内存中取出相应的方法来调用。
15.作为优选,通过事件存储订阅方将事件转发至数据库后,对事件进行序列化,基于事件的序列形式以及事件元数据将事件存储至数据库。
16.作为优选,通过disruptor组件,分布式的将事件分发并保存至存储数据库,通过mq组件将事件分发至即时转发订阅方。
17.作为优选,所述eventbus作为事件总线,在事件总线上配置拦截器,向命令添加额外的处理,且无需考虑命令的类型或名称,包括日志记录、安全/授权、监控、负载均衡。
18.作为优选,当聚合存活事件超过阈值、且聚合的状态不断发生变化,所述聚合引发多个事件,通过定期创建和存储快照事件的方式,将所述多个事件总结为单个事件,基于所述单个事件,通过聚合根重建聚合的状态。
19.第二方面,本发明的基于领域事件和事件溯源的代码结构优化系统,执行如第一方面任一项所述的基于领域事件和事件溯源的代码结构优化方法,所述系统包括:
20.配置模块,所述配置模块用于创建并配置聚合和领域服务,所述聚合为一组相关对象的集合,作为整体对外,并具有如下原则:具有唯一标识、为小聚合、通过唯一标识引用其它聚合、在聚合边界之外使用最终一致性,所述小聚合理解为作为集合其对象数量小于阈值;
21.事件创建模块,所述事件创建模块与所述事件创建模块交互,用于在命令的引发下,通过聚合或领域服务创建一个具有唯一标识符的事件,将所述事件包装在一个eventmessage中,所述eventmessage中包括用于标识事件的标识符、用于标识事件来源的消息类型、事件元数据、有效载荷以及时间戳;
22.事件分发模块,所述事件分发模块与所述事件创建模块交互,用于基于观察者模式,通过eventbus将事件分发至事件订阅方,所述事件订阅方包括事件存储订阅方、即时转发订阅方以及其他订阅方,所述eventbus包括disruptor组件、mq组件以及其他组件,所述disruptor组件用于将事件分发至数据库,并对事件进行序列化,基于事件的序列形式以及事件元数据将事件存储至数据库,所述mq组件用于将事件分发至即时转发订阅方,所述其他组件用于将事件分发至其他订阅方;
23.数据库,所述数据库与所述数据分发模块交互,用于存储事件;
24.转发器,所述转发器与所述数据库交互,用于转发事件;
25.消息队列,所述消息队列与所述事件分发模块和转发器交互,用于将事件转发至远程订阅方;
26.聚合重建模块,所述聚合重建模块用于基于聚合生成的系列事件,通过聚合根重建聚合的状态。
27.作为优选,在java项目中,所述事件创建模块用于对于命令使用@commandhandler注解,通过反射把注解的方法保存在内存中,将命令名作为key,将被注解的方法作为value,当命令总线接受的命令时,在内存中取出相应的方法来调用;
28.所述eventbus作为事件总线,在事件总线上配置拦截器,向命令添加额外的处理,且无需考虑命令的类型或名称,包括日志记录、安全/授权、监控、负载均衡;
29.当聚合存活事件超过阈值、且聚合的状态不断发生变化,所述聚合引发多个事件,所述聚合重建模块用于通过定期创建和存储快照事件的方式,将所述多个事件总结为单个事件,基于所述单个事件,通过聚合根重建聚合的状态。
30.本发明的基于领域事件和事件溯源的代码结构优化方法及系统具有以下优点:
31.1、使用事件驱动可以进一步减轻了系统之间的耦合,更容易实现serverless;如
果某个系统出现bug,根据历史事件可以追溯出正确的值;
32.2、事件驱动天然是可审计的,无需单独的审计日志模块,可以轻易查询出历史执行过的命令,以及命令导致的在各个子系统传播的事件;
33.3、可以更彻底的隔离了读和写,传统的写法如果在find/get中不小心调了update,隐式的副作用往往会导致非常难查的bug,一切基于命令和事件的思维,能够杜绝读写职责不清晰带来的不确定的副作用。
附图说明
34.为了更清楚地说明本发明实施例中的技术方案,下面将对实施例或现有技术描述中所需要使用的附图作简单地介绍,显而易见地,下面描述中的附图仅仅是本发明的一些实施例,对于本领域的普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
35.下面结合附图对本发明进一步说明。
36.图1为实施例1基于领域事件和事件溯源的代码结构优化方法的工作流程框图。
具体实施方式
37.下面结合附图和具体实施例对本发明作进一步说明,以使本领域的技术人员可以更好地理解本发明并能予以实施,但所举实施例不作为对本发明的限定,在不冲突的情况下,本发明实施例以及实施例中的技术特征可以相互结合。
38.本发明实施例提供基于领域事件和事件溯源的代码结构优化方法及系统,用于解决如何降低业务逻辑复杂度的技术问题。
39.实施例1:
40.本发明基于领域事件和事件溯源的代码结构优化方法,包括如下步骤:
41.s100、在命令的引发下,通过聚合或领域服务创建一个具有唯一标识符的事件,将所述事件包装在一个eventmessage中;
42.s200、基于观察者模式,通过eventbus将事件分发至事件订阅方,所述事件订阅方包括事件存储订阅方、即时转发订阅方以及其他订阅方;
43.s300、对于事件,通过事件存储订阅方将事件转发并存储数据库,通过即时转发订阅方将事件转发至消息队列,通过转发器将数据库中事件转发至消息队列;
44.s400、基于聚合生成的系列事件,通过聚合根重建聚合的状态。
45.本实施例中,aggregate(聚合)是一组相关对象的集合,作为一个整体被外界访问。设计良好的聚合应该要靠一下几个原则:
46.1、具有唯一标识;
47.2、尽可能设计小聚合;
48.3,通过唯一标识引用其他聚合;
49.4、在聚合边界之外使用最终一致性。
50.在实际项目中,还充斥着大量不属于聚合的行为,也就是静态方法,与其让它们分散在项目各个地方,不如做成统一的服务,也就是“领域服务”。事件就是由聚合或领域服务创建的。
51.命令,是用来描述改变应用程序状态的意图,在应用中可以将命令设计为一个不可变的pojo。命令总是有一个确切的目的地,虽然发送者并不关心由哪个服务来处理命令或该服务驻留在哪里,但它对它的结果感兴趣,所以我们会给命令设置回调函数,在命令发送后允许返回结果。
52.步骤s100中,当聚合或领域服务收到“命令”后,将会引发一个事件。在一个具体的实施中会把它包装在一个eventmessage中。事件最重要的便是它的唯一标识,除此之外还有标识事件来源的消息类型,事件元数据(metadata)、有效载荷(payload)以及时间戳。
53.在java项目中,可以使用注解进行开发。对于命令我们使用@commandhandler注解,然后通过反射把注解的方法保存在内存中,一般以命令名为key被注解的方法为value。然后当命令总线接受的命令时,在内存中取出相应的方法来调用。
54.领域事件构建方法如下:
[0055][0056][0057]
事件是核心,其为描述应用程序中已经发生的事情的对象。通常由“命令”触发。当聚合中发生重要的事情时,它将引发一个事件。事件可以是任何对象,是可以序列化与持久化的。当事件被分发时,我们会把他封装在一个eventmessage中,然后通过事件分发器,分发到各个事件订阅方。根据各个订阅方功能的不同,事件得到不同的处理。
[0058]
步骤s200为事件的分发。在一个具体的实施中,事件的发布采用观察者(observer)模式,这种方法可以实现模型与外部组件的解耦。可以根据项目需求实现几种事件发布器和不同功能的事件订阅者,诸如事件存储订阅方、即时转发订阅方以及其他订
阅方。
[0059]
eventbus是将事件分发到订阅该事件的处理程序上的机制。它支持订阅和跟踪事件处理结果,同时也可以持久化事件,这允许在稍后的阶段可以重放它们。
[0060]
借助disruptor组件,实现分布式的事件发布和存储功能。借助一些mq组件,将其发布到各种mq消息队列,实现分布式事务的发布。
[0061]
eventbus是事件总线,在事件总线上可以配置拦截器,向命令添加额外的处理,而不用考虑它们的类型或名称,例如日志记录、安全(授权)、监控、负载均衡等。
[0062]
步骤s300为将事件的存储以及事件的转发。
[0063]
实现存储的事件必须具有唯一的标识符,在一个具体的实施中,通过事件存储订阅方将事件转发至数据库后,对事件进行序列化,基于事件的序列形式以及事件元数据将事件存储至数据库。
[0064]
消息队列中事件有两种来源,一种为通过转发器,将数据库中存储的事件转发至消息队列,一种为通过即时转发订阅方,将事件转发至消息队列,该消息队列可将事件分发至远程订阅方。
[0065]
步骤s400为基于事件对聚合的重建。
[0066]
聚合根能够根据事件重建它们的状态,也可以配置为通过事件源存储库加载。这些存储库不存储聚合本身,但存储聚合生成的一系列事件。基于这些事件,可以随时恢复聚合的状态。
[0067]
jpaeventstorageengine用于在一个与jpa兼容的数据源中存储事件。jpa事件存储存将事件储在所谓的条目中。这些条目包含事件的序列化形式,以及存储元数据以便快速查找这些条目的一些字段。
[0068]
当聚合存活很长时间,并且它们的状态不断变化时,它们将产生大量的事件。必须加载所有这些事件来重建一个聚集的状态可能会有很大的性能影响。快照事件是具有特殊用途的领域事件:它将任意数量的事件总结为单个事件。通过定期创建和存储快照事件,事件存储并不需要返回事件的长列表。仅仅返回最后一个快照事件以及在快照之后发生的所有事件。
[0069]
快照创建可以由许多因素触发,例如自上一个快照以来创建的事件的数量,初始化聚合的时间超过了某个阈值,基于时间的等等。
[0070]
即当聚合存活事件超过阈值、且聚合的状态不断发生变化,聚合引发多个事件,通过定期创建和存储快照事件的方式,将所述多个事件总结为单个事件,基于所述单个事件,通过聚合根重建聚合的状态。
[0071]
本实施例的方法根据领域驱动设计的思想,降低业务逻辑复杂度,构建“充血模型”与“聚合”。并使用“领域事件”来描述与处理业务模型里的行为。这样可以将处理的流程解耦,实现系统的可扩展性,提高主业务流程的内聚性。该方法产生了如下目的:
[0072]
一,实现业务与模块间的解耦,事件发布者和订阅者不需要预先知道彼此的存在。
[0073]
二,异步消息传递,业务逻辑和事件可以同步发生。
[0074]
三,多对多的交互,实现分布式发布订阅模型。
[0075]
四,使架构具有持久化历史命令与执行结果的能力,且可通过快照恢复历史状态。
[0076]
实施例2:
[0077]
本发明基于领域事件和事件溯源的代码结构优化系统,包括配置模块、事件创建模块、事件分发模块、数据库、转发器、消息队列以及聚合重建模块。该模块可执行实施例1公开的方法。
[0078]
配置模块用于创建并配置聚合和领域服务,所述聚合为一组相关对象的集合,作为整体对外,并具有如下原则:具有唯一标识、为小聚合、通过唯一标识引用其它聚合、在聚合边界之外使用最终一致性,所述小聚合理解为作为集合其对象数量小于阈值。
[0079]
在一个具体的实施中,aggregate(聚合)是一组相关对象的集合,作为一个整体被外界访问。设计良好的聚合应该要靠一下几个原则:
[0080]
1、具有唯一标识;
[0081]
2、尽可能设计小聚合;
[0082]
3,通过唯一标识引用其他聚合;
[0083]
4、在聚合边界之外使用最终一致性。
[0084]
在实际项目中,还充斥着大量不属于聚合的行为,也就是静态方法,与其让它们分散在项目各个地方,不如做成统一的服务,也就是“领域服务”。事件就是由聚合或领域服务创建的。
[0085]
命令,是用来描述改变应用程序状态的意图,在应用中可以将命令设计为一个不可变的pojo。命令总是有一个确切的目的地,虽然发送者并不关心由哪个服务来处理命令或该服务驻留在哪里,但它对它的结果感兴趣,所以我们会给命令设置回调函数,在命令发送后允许返回结果。
[0086]
事件创建模块与所述事件创建模块交互,用于在命令的引发下,通过聚合或领域服务创建一个具有唯一标识符的事件,将所述事件包装在一个eventmessage中,所述eventmessage中包括用于标识事件的标识符、用于标识事件来源的消息类型、事件元数据、有效载荷以及时间戳。
[0087]
在一个具体的实施中,当聚合或领域服务收到“命令”后,将会引发一个事件,并包装在一个eventmessage中。事件最重要的便是它的唯一标识,除此之外还有标识事件来源的消息类型,事件元数据(metadata)、有效载荷(payload)以及时间戳。
[0088]
在java项目中,可以使用注解进行开发。对于命令我们使用@commandhandler注解,然后通过反射把注解的方法保存在内存中,一般以命令名为key被注解的方法为value。然后当命令总线接受的命令时,在内存中取出相应的方法来调用。
[0089]
领域事件构建方法如下:
[0090][0091][0092]
事件是核心,其为描述应用程序中已经发生的事情的对象。通常由“命令”触发。当聚合中发生重要的事情时,它将引发一个事件。事件可以是任何对象,是可以序列化与持久化的。当事件被分发时,我们会把他封装在一个eventmessage中,然后通过事件分发模块分发到各个事件订阅方。根据各个订阅方功能的不同,事件得到不同的处理。
[0093]
事件分发模块与事件创建模块交互,用于基于观察者模式,通过eventbus将事件分发至事件订阅方,事件订阅方包括事件存储订阅方、即时转发订阅方以及其他订阅方,所述eventbus包括disrutor组件、mq组件以及其他组件,disruptor组件用于将事件分发至数据库,并对事件进行序列化,基于事件的序列形式以及事件元数据将事件存储至数据库,mq组件用于将事件分发至即时转发订阅方,其他组件用于将事件分发至其他订阅方。
[0094]
事件的发布采用观察者(observer)模式,这种方法可以实现模型与外部组件的解耦。可以根据项目需求实现几种事件发布器和不同功能的事件订阅者,诸如事件存储订阅方、即时转发订阅方以及其他订阅方。
[0095]
eventbus是将事件分发到订阅该事件的处理程序上的机制。它支持订阅和跟踪事件处理结果,同时也可以持久化事件,这允许在稍后的阶段可以重放它们。
[0096]
借助disruptor组件,实现分布式的事件发布和存储功能。借助一些mq组件,将其发布到各种mq消息队列,实现分布式事务的发布。
[0097]
eventbus是事件总线,在事件总线上可以配置拦截器,向命令添加额外的处理,而不用考虑它们的类型或名称,例如日志记录、安全(授权)、监控、负载均衡等。
[0098]
数据库与数据分发模块交互,用于存储事件。实现存储的事件必须具有唯一的标识符,在一个具体的实施中,通过事件存储订阅方将事件转发至数据库后,对事件进行序列化,基于事件的序列形式以及事件元数据将事件存储至数据库。即在数据库中事件内容包括事件的序列形式以及事件元数据。
[0099]
消息队列与事件分发模块和转发器交互,用于将事件转发至远程订阅方。即消息队列中事件有两种来源,一种为通过转发器,将数据库中存储的事件转发至消息队列,一种为通过即时转发订阅方,将事件转发至消息队列,该消息队列可将事件分发至远程订阅方。
[0100]
聚合重建模块用于基于聚合生成的系列事件,通过聚合根重建聚合的状态。
[0101]
聚合根能够根据事件重建它们的状态,也可以配置为通过事件源存储库加载。这些存储库不存储聚合本身,但存储聚合生成的一系列事件。基于这些事件,可以随时恢复聚合的状态。
[0102]
jpaeventstorageengine用于在一个与jpa兼容的数据源中存储事件。jpa事件存储存将事件储在所谓的条目中。这些条目包含事件的序列化形式,以及存储元数据以便快速查找这些条目的一些字段。
[0103]
当聚合存活很长时间,并且它们的状态不断变化时,它们将产生大量的事件。必须加载所有这些事件来重建一个聚集的状态可能会有很大的性能影响。快照事件是具有特殊用途的领域事件:它将任意数量的事件总结为单个事件。通过定期创建和存储快照事件,事件存储并不需要返回事件的长列表。仅仅返回最后一个快照事件以及在快照之后发生的所有事件。
[0104]
快照创建可以由许多因素触发,例如自上一个快照以来创建的事件的数量,初始化聚合的时间超过了某个阈值,基于时间的等等。
[0105]
上文通过附图和优选实施例对本发明进行了详细展示和说明,然而本发明不限于这些已揭示的实施例,基与上述多个实施例本领域技术人员可以知晓,可以组合上述不同实施例中的代码审核手段得到本发明更多的实施例,这些实施例也在本发明的保护范围之内。
再多了解一些

本文用于企业家、创业者技术爱好者查询,结果仅供参考。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表

相关文献