java - 如何使用事件源(轴突框架)处理从传奇中的 REST-API 传递的多个实体?
问题描述
所以目前我正在使用事件溯源和 CQRS 实现一个带有轴突框架的传奇。
情况如下:
我有 3 个微服务,m1、m2 和 m3
用户在 GUI 中输入 3 个实体 e1、e2、e3 的数据,这些数据分别由 m1、m2、m3 处理和持久化,因此 m1->e1,m2->e2,m3->e3
现在到传奇的必要性:
没有e2就不能存在e1,没有e3就不能存在e2。
因此,所有 3 个实体都必须由各自的服务成功创建,如果一个失败,saga 需要执行补偿事务以确保一致性。首先 m1 创建 e1,发出一个 e1CreatedEvent 并且一个协调器发送一个 createE2Command 作为对它的反应等等。
现在我的问题:
如何获取/存储用户输入的信息?在单个 RequestBody 中?那我该怎么处理这些数据呢?因为它需要以某种方式缓存才能与命令一起发送。
例如 m1 创建一个 createE1Command 并将来自 e1 的信息添加到它,然后在它成功创建后,编排器将启动一个 createE2Command 并在发送之前将 e2 的信息添加到该命令中......为此, e2 的信息需要以某种方式存储,直到需要它为止。
示例代码:
@Saga
public class ManagementSaga{
@Autowired
private transient CommandGateway commandGateway
@StartSaga
@SagaEventhandler
public void handle (e1CreatedEvent e1CreatedEvent){
commandGateway.send (new CreateE2Command (e1CreatedEvent.Id, **HERE NEEDS TO BE THE INFO THAT THE USER CREATED PREVIOUSLY**)}}
我是否只是创建一个包含这三个实体信息的对象?这感觉真的不对。
现在我明白了,选择这样一个领域模型可能真的很糟糕,如果可能的话应该避免它,但这是为了科学:-)
解决方案
在这种情况下,我的第一反应是完全质疑设计。(微)服务似乎是围绕实体设计的。这种类型的设计可能在某些情况下有效,但在其他情况下不可避免地会导致分布式单体。您面临的挑战暗示了后者。
从 API 的角度来看,交互和系统的设计方式似乎也存在不匹配。虽然没有按照定义错误,但这也可能表明 API 不正确(不能正确反映系统的行为),或者行为模型不正确。
无论如何,为了给您一个希望比“它取决于”更有用的答案,您可以在多个命令甚至查询中获得单个交互结果。在所有情况下,它都不需要 Saga。
使用有关 E1、E2 和 E3 的信息进行单个请求。然后在您的控制器中,发送命令以创建 E3,根据该命令的结果创建 E2,最后创建 E1。没有信息需要“缓存”。请求信息在整个过程中都是可用的。然而,这种方法不是事务性的。如果服务崩溃,它可能会使进程半执行。
另一种方法是使用一个命令处理程序来注册用户的原始意图。那不是要创建 E1、E2 或 E3,而是要包含所有三者。进程生成的事件会触发 Saga 单独执行每个步骤,使用这些步骤中的事件来触发下一步。这个过程是事务性的,具有最终一致性特征。
我希望这有点道理。但是,我会认真重新考虑服务的模型/设计,让他们更多地关注流程(步骤),而不是实体(状态)。我见过太多的微服务项目因为以实体为中心的设计而失败......
推荐阅读
- assembly - 我正在尝试在 BCD 中添加两个数字。如何使用进位逐位添加两个十六进制值?
- tinymce - tinyMCE base64 Image and storing to mySQL database
- typescript - Testing Connection to Firebase Real-Time Database, Hitting a ref to Confirm Connection
- unity3d - Unity - following finger only works for one direction
- python - TypeError:在方法“...”中,使用 swig 模块时类型为“unsigned char const *”的参数 1
- android - html progress bar not working in android browsers
- android - fitsSystemWindows is not working with support libraries 27.1.1
- java - Java | Posing Boolean expressions on hashMap entries
- java - Using iterator object to loop throuh arraylist and check if it is higher than a value
- c# - How to use Microsoft.Build in .NET Core project?