Axonframework,有没有办法使用命令总线来锁定聚合
Axonframework, is there a way to lock aggregate using the command bus instead
我有两个具有相同标识符的聚合。我知道这听起来可能很奇怪,但我想这样做的原因是因为 BaseAggregate 有太多的功能,我想分离代码库,这样它仍然能够维护,也能够规模化。因此,FooAggregate 上的开发人员可以专注于自己的功能,同时共享 BarAggregate 上的开发人员可能需要的一些状态。这是同时向 FooAggregate 和 BarAggregate 发送命令时的问题,它与 aggregateSequenceNumber 在活动商店。所以我做了很多研究,发现只要有命令被执行,聚合就会被锁定,但是这两个聚合部署在不同的 JVM 上,所以它不会阻止彼此执行命令。我希望它在命令总线上完成。所以假设 FooCommand 和 BarCommand (具有相同的标识符)同时被调度。我希望命令总线等待 FooCommand 或 BarCommand 成功,然后执行下一个命令。有没有一种方法可以将命令总线配置为这样的行为,它会影响性能吗?
abstract class BaseAggregate {
@AggregateIdentifier
public String identifier;
// I use event-sourced approach so this state can be build up from events (with the same identifier)
// and share among other services
public List<String> sharedState;
}
class FooAggregate extends BaseAggregate {
public void handle(FooCommand command) {
// apply event
}
}
class BarAggregate extends BaseAggregate {
public void handle(BarCommand command) {
// apply event
}
}
在转到您的确切问题之前,让我重点关注以下内容:
So developers on FooAggregate can focus on their own features while shared some state that may need from the developers on BarAggregate.
您不应将状态从一个聚合实例读入另一个。聚合实例是独立的单元,它们在自己的 状态下执行验证。如果应扩大一致性边界以在您的系统中包含更多实体,则意味着您具有更大的聚合范围。
话虽如此,我猜您的问题措辞可能有点不对。我的依据是您正在使用 polymorphic aggregate,这是为您的域建模的好方法。从您的问题描述和代码中不清楚的是,您是否正确配置了它。
如果您正在使用 Spring,您可以将 Axon 的 @Aggregate
注释放在父 class 上。在你的例子中,就是 BaseAggregate
。这将正确地告诉 Axon Framework 它正在处理多态聚合。
如果您不使用 Spring,则必须像这样使用 AggregateConfigurer
:
AggregateConfigurer<BaseAggregate> configurer =
AggregateConfigurer.defaultConfiguration(BaseAggregate.class)
.withSubtype(FooAggregate.class)
.withSubtype(BarAggregate.class);
话虽如此,我们可以继续讨论您实际要问的问题。
CommandBus
是否可以为您锁定聚合
Axon Framework 的锁定方案适用于 Repository
。
更具体地说,有一个 LockingRepository
class 由 Axon Framework 中的 any Repository
实现。
该组件确保任何时候聚合被加载,它都会被锁定,确保不会发生重复访问。
但是,锁不是分布式锁,因为它本身会产生其他问题的整个方案。因此,为简单起见,这就是它所在的位置。
知道这一点,命令总线的任务不是锁定,而是命令总线确保同一聚合的命令一致路由。这实际上就是 Axon Frameworks 分布式命令总线所做的!
如果您使用 Axon 服务器,该行为将是无缝的。
请注意,这适用于 Axon Server 的标准版(免费)和企业版。如果愿意,您甚至可以选择 AxonIQ Cloud。
如果您不使用 Axon 服务器,则必须自己设置分布式命令总线。这可以通过 Axon 的 Spring Cloud or JGroups 扩展来完成。
我有两个具有相同标识符的聚合。我知道这听起来可能很奇怪,但我想这样做的原因是因为 BaseAggregate 有太多的功能,我想分离代码库,这样它仍然能够维护,也能够规模化。因此,FooAggregate 上的开发人员可以专注于自己的功能,同时共享 BarAggregate 上的开发人员可能需要的一些状态。这是同时向 FooAggregate 和 BarAggregate 发送命令时的问题,它与 aggregateSequenceNumber 在活动商店。所以我做了很多研究,发现只要有命令被执行,聚合就会被锁定,但是这两个聚合部署在不同的 JVM 上,所以它不会阻止彼此执行命令。我希望它在命令总线上完成。所以假设 FooCommand 和 BarCommand (具有相同的标识符)同时被调度。我希望命令总线等待 FooCommand 或 BarCommand 成功,然后执行下一个命令。有没有一种方法可以将命令总线配置为这样的行为,它会影响性能吗?
abstract class BaseAggregate {
@AggregateIdentifier
public String identifier;
// I use event-sourced approach so this state can be build up from events (with the same identifier)
// and share among other services
public List<String> sharedState;
}
class FooAggregate extends BaseAggregate {
public void handle(FooCommand command) {
// apply event
}
}
class BarAggregate extends BaseAggregate {
public void handle(BarCommand command) {
// apply event
}
}
在转到您的确切问题之前,让我重点关注以下内容:
So developers on FooAggregate can focus on their own features while shared some state that may need from the developers on BarAggregate.
您不应将状态从一个聚合实例读入另一个。聚合实例是独立的单元,它们在自己的 状态下执行验证。如果应扩大一致性边界以在您的系统中包含更多实体,则意味着您具有更大的聚合范围。
话虽如此,我猜您的问题措辞可能有点不对。我的依据是您正在使用 polymorphic aggregate,这是为您的域建模的好方法。从您的问题描述和代码中不清楚的是,您是否正确配置了它。
如果您正在使用 Spring,您可以将 Axon 的 @Aggregate
注释放在父 class 上。在你的例子中,就是 BaseAggregate
。这将正确地告诉 Axon Framework 它正在处理多态聚合。
如果您不使用 Spring,则必须像这样使用 AggregateConfigurer
:
AggregateConfigurer<BaseAggregate> configurer =
AggregateConfigurer.defaultConfiguration(BaseAggregate.class)
.withSubtype(FooAggregate.class)
.withSubtype(BarAggregate.class);
话虽如此,我们可以继续讨论您实际要问的问题。
CommandBus
是否可以为您锁定聚合
Axon Framework 的锁定方案适用于 Repository
。
更具体地说,有一个 LockingRepository
class 由 Axon Framework 中的 any Repository
实现。
该组件确保任何时候聚合被加载,它都会被锁定,确保不会发生重复访问。
但是,锁不是分布式锁,因为它本身会产生其他问题的整个方案。因此,为简单起见,这就是它所在的位置。
知道这一点,命令总线的任务不是锁定,而是命令总线确保同一聚合的命令一致路由。这实际上就是 Axon Frameworks 分布式命令总线所做的!
如果您使用 Axon 服务器,该行为将是无缝的。 请注意,这适用于 Axon Server 的标准版(免费)和企业版。如果愿意,您甚至可以选择 AxonIQ Cloud。
如果您不使用 Axon 服务器,则必须自己设置分布式命令总线。这可以通过 Axon 的 Spring Cloud or JGroups 扩展来完成。