所以目前我正在使用事件源和CQRS来实现轴突框架的传奇。
情况如下:
我有3个微服务,分别是m1,m2和m3
用户在GUI中输入3个实体e1,e2,e3的数据,分别由m1,m2,m3处理和保留,因此m1-> e1,m2-> e2,m3-> e3
现在有了传奇的必要性:
没有e2不能存在e1,没有e3不能存在e2。
因此,必须通过各自的服务成功创建所有3个实体,如果一个实体失败,则传奇需要执行补偿交易以确保一致性。 首先,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**)}}
我是否仅创建一个对象来保存这三个实体的信息?感觉真不对。
现在我了解到,选择这样一种域模型也许真的很糟糕,如果可能的话,应该避免使用它,但这是出于科学目的:-)
答案 0 :(得分:2)
在这种情况下,我的第一反应是完全质疑设计。似乎(微)服务是围绕实体设计的。这种设计在某些情况下可能会起作用,但在其他情况下不可避免地会导致分布式整体。您面临的挑战暗示了后者。
从API的角度和系统的设计方式来看,交互似乎也不匹配。虽然不是每个定义都错误,但这也可能表示API不正确(不能正确反映系统的行为)或行为模型不正确。
无论如何要给您一个比“取决于它”更有用的答案,您可以在多个命令甚至查询中获得单个交互结果。并非在所有情况下都需要佐贺。
发出一个有关E1,E2和E3信息的单个请求。然后在您的控制器中,发送命令以创建E3,然后根据该命令的结果创建E2,最后创建E1。无需“缓存”任何信息。请求信息在整个过程中都可用。但是,这种方法不是事务性的。如果服务崩溃,则可能会使进程半执行。
一种替代方法是让命令处理程序注册用户的原始意图。那不是要创建E1,E2或E3,而是要包含所有这三个。流程生成的事件会触发Saga单独执行每个步骤,并使用这些步骤中的事件来触发下一步。此过程具有最终一致性特征。
我希望这有道理。但是,我会认真地重新考虑服务的模型/设计,使它们更多地关注流程(步骤),而不是实体(状态)。我已经看到太多的微服务项目由于以实体为中心的设计而失败...