百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 文章教程 > 正文

Axon Framework - Command 基础设施

xsobi 2024-12-18 17:46 2 浏览

基础设施

命令调度,如 《Axon Framework - Command 调度程序》所示,具有许多优点。 首先,它构造一个清楚地描述客户意图的对象。 通过记录命令,您可以存储意图和相关数据以供将来参考。 命令处理还可以轻松地将命令处理组件公开给远程客户端,例如通过 Web 服务。

测试也变得容易得多。 您可以通过列出许多事件和命令来定义开始情况(given)、要执行的命令(when)和预期结果(then)来定义测试脚本(有关此内容的更多信息,请参阅测试)。

最后一个主要优点是在同步和异步之间以及本地和分布式命令处理之间切换非常容易。

这并不意味着使用显式命令对象进行命令调度是唯一的方法。 Axon 的目标不是规定特定的工作方式,而是支持您按照自己的方式进行操作,同时提供最佳实践作为默认行为。 仍然可以使用可以调用来执行命令的服务层。 该方法只需要启动一个工作单元(请参阅工作单元)并在方法完成时对其执行提交或回滚。

接下来的部分概述了与使用 Axon Framework 设置命令调度基础设施相关的任务。 提到了 API 友好的 CommandGateway,以及本地和分布式环境中的 CommandBus

命令网关

命令网关是对命令调度机制的方便接口。 虽然您不需要使用网关来分派命令,但它通常是最简单的选择。

有两种使用命令网关的方法。 第一种是使用Axon提供的 CommandGateway 接口和 DefaultCommandGateway 实现。 命令网关提供了许多方法,允许您同步、超时或异步发送命令并等待结果。

另一种选择可能是最灵活的。 您可以使用 CommandGatewayFactory 将几乎任何接口变成命令网关。 这允许您使用强类型定义应用程序的界面并声明您自己的(检查的)业务异常。 Axon 将在运行时自动为该接口生成一个实现。

配置命令网关

您的自定义命令网关和 Axon 提供的命令网关都需要至少配置一个命令总线。 另外,命令网关可以配置一个 RetrySchedulerCommandDispatchInterceptorCommandCallback

RetryScheduler

RetryScheduler 能够在命令执行失败时安排重试。 当命令由于显式非瞬态异常而失败时,根本不会重试。 请注意,仅当命令由于 RuntimeException 而失败时才会调用重试调度程序。 已检查的异常被视为 "business exception",永远不会触发重试。

目前,存在两种实现:

  1. IntervalRetryScheduler 将按设定的时间间隔重试给定的命令,直到成功,或已达到最大重试次数。
  2. ExponentialBackOffIntervalRetryScheduler 以指数回退间隔重试失败的命令,直到 它成功了,或者已经进行了最大次数的重试。

CommandDispatchInterceptor

CommandDispatchInterceptor 允许在将 CommandMessage 分派到命令总线之前对其进行修改。 与在命令总线上配置的 CommandDispatchInterceptor 相比,这些拦截器仅在通过此网关发送消息时才被调用。 例如,这些拦截器可用于将元数据附加到命令或执行验证。

CommandCallback

可以在常规 send 时向命令网关提供 CommandCallback,指定如何处理命令处理结果。 它适用于 CommandMessageCommandResultMessage 类,因此允许通过此网关发送的所有命令的一些通用行为,无论它们的类型如何。

创建自定义命令网关

Axon 允许将自定义接口用作命令网关。 接口中声明的每个方法的行为基于参数类型、返回类型和声明的异常。 使用这个网关不仅方便,而且允许您在需要的地方模拟您的接口,从而使测试变得更加容易。

这是参数如何影响命令网关的行为:

  • 第一个参数应该是要调度的实际命令对象。
  • 使用 @MetaDataValue 注解的参数将其值分配给元数据字段,并将标识符作为注解参数传递
  • MetaData 类型的参数将与 CommandMessage 上的 MetaData 合并。
    后面的参数定义的元数据将覆盖前面参数的元数据,如果它们的键相等。
  • CommandCallback 类型的参数将在处理命令后调用其 onResult(CommandMessage<? extends C>, CommandResultMessage<? extends R>)。 虽然 CommandCallback 提供了一种处理命令处理结果的方法,但这并不影响您是否可以在自定义命令网关上定义返回类型。 如果同时定义了回调和返回类型,则回调的调用将始终与返回值(或异常)匹配。 最后,要知道你可能会传入几个 CommandCallback 实例,它们都会被依次调用。
  • 最后两个参数表示超时,可能是 long (或 int)和 TimeUnit 类型。
    只要这些参数指示,该方法最多将阻塞。 方法对超时的反应取决于方法上声明的异常(见下文)。
    请注意,如果该方法的其他属性完全阻止阻塞,则永远不会发生超时。

方法声明的返回值也会影响其行为:

  • void 返回类型将导致该方法立即返回,除非该方法上有其他指示要等待,例如超时或声明的异常。
  • FutureCompletionStageCompletableFuture 的返回类型将导致方法立即返回。
    您可以使用从该方法返回的 CompletableFuture 实例访问命令处理程序的结果。
    方法上声明的异常和超时将被忽略。
  • 任何其他返回类型都将导致方法阻塞,直到结果可用。
    结果被强制转换为返回类型(如果类型不匹配,则会导致
    ClassCastException)。

异常具有以下效果:

  • 如果命令处理程序(或拦截器)抛出该类型的异常,则将抛出任何声明的检查异常。
    如果抛出未声明的已检查异常,则将其包装在
    CommandExecutionException 中,即 RuntimeException
  • 发生超时时,默认行为是从方法返回 null
    这可以通过声明 TimeoutException 来更改。
    如果声明了此异常,则会引发 TimeoutException
  • 当线程在等待结果时被中断,默认行为是返回 null。
    在这种情况下,中断标志会在线程上重新设置。
    通过在该方法上声明一个
    InterruptedException,此行为被更改为抛出该异常。
    抛出异常时去掉中断标志,符合 java 规范。
  • 可以在方法上声明其他运行时异常,但除了向 API 用户说明之外不会产生任何影响。

最后,可以使用注解:

  • 如参数部分所述,参数上的 @MetaDataValue 注解将添加该参数的值作为元数据值。
    元数据条目的键作为注解的参数提供。
  • 使用 @Timeout 注解的方法最多会阻塞指定的时间。
    如果方法声明了超时参数,则忽略此注解。
  • 使用 @Timeout 注解的类将导致该类中声明的所有方法最多阻塞指定的时间量,除非它们使用自己的 @Timeout 注解进行注解或指定超时参数。
  • public interface MyGateway { // 发送就忘记 void sendCommand(MyPayloadType command); // 附加元数据并将等待结果 10 秒的方法 @Timeout(value = 10, unit = TimeUnit.SECONDS) ReturnValue sendCommandAndWaitForAResult(MyPayloadType command, @MetaDataValue("userId") String userId); // 在超时时引发异常的替代方案 @Timeout(value = 20, unit = TimeUnit.SECONDS) ReturnValue sendCommandAndWaitForAResult(MyPayloadType command) throws TimeoutException, InterruptedException; // 这个方法也会等待,调用者决定多长时间 void sendCommandAndWait(MyPayloadType command, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException; } // 配置网关: CommandGatewayFactory factory = CommandGatewayFactory.builder() .commandBus(commandBus) .build(); // 注意 commandBus 可以从 Configuration 中获取 // 在 `configurer.initialize()` 上返回的对象。 MyGateway myGateway = factory.createGateway(MyGateway.class);

命令总线 - 本地

本地命令总线是将命令分派到 Axon 应用程序中它们各自的命令处理程序的机制。 可以在此处找到有关如何使用 CommandBus 的建议。 框架中存在多种具有不同特性的命令总线。

SimpleCommandBus

顾名思义,SimpleCommandBus 是最简单的实现。 它在调度它们的线程中直接处理命令。 处理命令后,修改的聚合被保存,生成的事件在同一线程中发布。 在大多数情况下,例如 Web 应用程序,此实现将满足您的需求。

与大多数 CommandBus 实现一样,SimpleCommandBus 允许配置拦截器。 当在命令总线上调度命令时调用 CommandDispatchInterceptorCommandHandlerInterceptor 在实际的命令处理程序方法之前被调用,允许您修改或阻止命令。 有关详细信息,请参阅命令拦截器。

由于所有命令处理都在同一个线程中完成,因此这种实现仅限于 JVM 的边界。 这个实现的性能很好,但并不特别。 要跨越 JVM 边界,或充分利用 CPU 周期,请查看其他 CommandBus 实现。

Axon 配置 API

Configurer configurer =
    DefaultConfigurer.defaultConfiguration()
                     .configureCommandBus(
                        c -> SimpleCommandBus.builder()
                                             .transactionManager(c.getComponent(TransactionManager.class))
                                             .messageMonitor(c.messageMonitor(SimpleCommandBus.class, "commandBus"))
                                             .build()
                     );

Spring Boot AutoConfiguration

@Bean
public SimpleCommandBus commandBus(TransactionManager txManager, AxonConfiguration axonConfiguration) {
    SimpleCommandBus commandBus =
            SimpleCommandBus.builder()
                            .transactionManager(txManager)
                            .messageMonitor(axonConfiguration.messageMonitor(CommandBus.class, "commandBus"))
                            .build();
    commandBus.registerHandlerInterceptor(
            new CorrelationDataInterceptor<>(axonConfiguration.correlationDataProviders())
    );
    return commandBus;
}

AsynchronousCommandBus

顾名思义,AsynchronousCommandBus 实现从调度命令的线程异步执行命令。 它使用 Executor 在不同的线程上执行实际的处理逻辑。

默认情况下,AsynchronousCommandBus 使用无界缓存线程池。 这意味着在调度命令时会创建一个线程。 已完成处理命令的线程将重新用于新命令。 如果线程在 60 秒内未处理命令,则线程将被停止。

或者,可以提供一个 Executor 实例来配置不同的线程策略。

请注意,停止应用程序时应关闭 AsynchronousCommandBus,以确保正确关闭所有等待的线程。 要关闭,请调用 shutdown() 方法。 如果它实现了 ExecutorService 接口,这也将关闭任何提供的 Executor 实例。

Axon 配置 API

Configurer configurer = DefaultConfigurer.defaultConfiguration()
            .configureCommandBus(c -> AsynchronousCommandBus.builder().transactionManager(c.getComponent(TransactionManager.class))
            .messageMonitor(c.messageMonitor(AsynchronousCommandBus.class, "commandBus"))
            .build());

Spring Boot AutoConfiguration

@Bean
public AsynchronousCommandBus commandBus(TransactionManager txManager, AxonConfiguration axonConfiguration) {
    AsynchronousCommandBus commandBus =
            AsynchronousCommandBus.builder()
                            .transactionManager(txManager)
                            .messageMonitor(axonConfiguration.messageMonitor(AsynchronousCommandBus.class, "commandBus"))
                            .build();
    commandBus.registerHandlerInterceptor(new CorrelationDataInterceptor<>(axonConfiguration.correlationDataProviders()));
    return commandBus;
}

DisruptorCommandBus

SimpleCommandBus 具有合理的性能特征。 SimpleCommandBus 需要锁以防止多个线程同时访问同一个聚合,这一事实会导致处理开销和锁争用。

DisruptorCommandBus 采用不同的方法进行多线程处理。 不是让多个线程各自执行相同的进程,而是有多个线程,每个线程负责一个进程。 DisruptorCommandBus 使用 Disruptor,一个用于并发编程的小型框架,通过对多线程采用不同的方法来实现更好的性能。 不是在调用线程中进行处理,而是将任务移交给两组线程,每组线程负责处理的一部分。 第一组线程将执行命令处理程序,更改聚合的状态。 第二组将存储事件并将其发布到事件存储。

虽然 DisruptorCommandBus 的性能轻松超过 SimpleCommandBus 4 倍(!),但也有一些限制:

  • DisruptorCommandBus 仅支持事件溯源聚合。
    此命令总线还充当 Disruptor 处理的聚合的 Repository。
    要获取对 Repository 的引用,请使用 createRepository(AggregateFactory)
  • 命令只能导致单个聚合实例中的状态更改。
  • 使用缓存时,它只允许给定标识符的单个聚合。
    这意味着不可能有两个不同类型的聚合具有相同的标识符。
  • 命令通常不应导致需要回滚工作单元的故障。
    当发生回滚时,DisruptorCommandBus 不能保证命令按照它们被调度的顺序进行处理。
    此外,它需要重试许多其他命令,从而导致不必要的计算。
  • 在创建新的聚合实例时,更新创建的实例的命令可能不会全部按照提供的确切顺序发生。
    创建聚合后,所有命令将完全按照它们被分派的顺序执行。
    为确保顺序,请在创建命令上使用回调以等待创建聚合。
    它不应该超过几毫秒。

要构造 DisruptorCommandBus 实例,您需要一个 EventStore。 该组件在事件总线和事件存储部分中进行了解释。

或者,您可以提供 DisruptorConfiguration 实例,它允许您调整配置以优化特定环境的性能:

  • Buffer size - 环形缓冲区上用于注册传入命令的插槽数。
    更高的值可能会增加吞吐量,但也会导致更高的延迟。 必须始终是 2 的幂。默认为 4096。
  • ProducerType - 指示条目是由单个线程还是由多个线程产生的。 默认为多个。
  • WaitStrategy - 当处理器线程(负责实际处理的三个线程)需要相互等待时使用的策略。
    最佳等待策略取决于机器中可用的内核数量以及正在运行的其他进程的数量。
    如果低延迟至关重要,并且 DisruptorCommandBus 可能会为自己声明内核,则可以使用 BusySpinWaitStrategy
    要使命令总线占用更少的 CPU 并允许其他线程进行处理,请使用 YieldingWaitStrategy
    最后,您可以使用 SleepingWaitStrategyBlockingWaitStrategy 允许其他进程公平共享 CPU。
    如果不期望命令总线全时处理,则后者是合适的。
    默认为 BlockingWaitStrategy
  • Executor - 设置为 DisruptorCommandBus 提供线程的 Executor
    这个执行器必须能够提供至少四个线程。
    DisruptorCommandBus 的处理组件声明了三个线程。
    额外的线程用于调用回调并安排重试,以防检测到聚合的状态已损坏。
    默认为从名为 “DisruptorCommandBus” 的线程组提供线程的 CachedThreadPool
  • TransactionManager - 定义应确保在事务中执行事件的存储和发布的事务管理器。
  • InvokerInterceptors - 定义要在调用过程中使用的 CommandHandlerInterceptor
    这是调用实际命令处理程序方法的进程。
  • PublisherInterceptors - 定义要在发布过程中使用的 CommandHandlerInterceptor
    这是存储和发布生成的事件的过程。
  • RollbackConfiguration - 定义工作单元应在哪些异常上回滚。
    默认为在未经检查的异常上回滚的配置。
  • RescheduleCommandsOnCorruptState - 指示是否应重新安排针对已损坏(例如,因为工作单元回滚)的聚合执行的命令。
    如果为 false,将调用回调的 onFailure() 方法。
    如果为 true(默认值),则将改为重新安排命令。
  • CoolingDownPeriod - 设置等待的秒数以确保处理所有命令。
    在冷却期间,不接受新命令,但会处理现有命令,并在必要时重新安排。
    冷却期确保线程可用于重新调度命令和调用回调。
    默认为 1000(1 秒)。
  • Cache - 设置存储已从 Event Store 重建的聚合实例的缓存。
    缓存用于存储破坏者未在活动中使用的聚合实例。
  • InvokerThreadCount - 分配给命令处理程序调用的线程数。
    一个好的起点是机器中内核数量的一半。
  • PublisherThreadCount - 用于发布事件的线程数。
    一个好的起点是内核数量的一半,如果在 I/O 上花费大量时间,则可以增加。
  • SerializerThreadCount - 用于预序列化事件的线程数。
    这默认为 1,但如果未配置序列化程序,则将被忽略。
  • Serializer - 用于执行预序列化的序列化程序。
    配置序列化程序后,DisruptorCommandBus 会将所有生成的事件包装在 SerializationAware 消息中。
    有效负载和元数据的序列化形式在发布到事件存储之前附加。

Axon 配置 API

Configurer configurer = DefaultConfigurer.defaultConfiguration()
            .configureCommandBus(c ->
                DisruptorCommandBus.builder()
                    .transactionManager(c.getComponent(TransactionManager.class))
                    .messageMonitor(c.messageMonitor(DisruptorCommandBus.class, "commandBus"))
                    .bufferSize(4096)
                    .build()
            );

Spring Boot AutoConfiguration

@Bean
public DisruptorCommandBus commandBus(TransactionManager txManager, AxonConfiguration axonConfiguration) {
    DisruptorCommandBus commandBus =
            DisruptorCommandBus.builder()
                            .transactionManager(txManager)
                            .messageMonitor(axonConfiguration.messageMonitor(DisruptorCommandBus.class, "commandBus"))
                            .build();
    commandBus.registerHandlerInterceptor(new CorrelationDataInterceptor<>(axonConfiguration.correlationDataProviders()));
    return commandBus;
}

命令总线 - 分布式

通常,您希望不同 JVM 中的多个命令总线实例作为一个实例。 在一个 JVM 的命令总线上调度的命令应该无缝地传输到另一个 JVM 中的命令处理程序,同时发回任何结果。 这就是 'distributing the command bus' 概念的用武之地。

无论使用哪种分布式命令总线,都有几个概念是可配置的:

本地段

与本地 CommandBus 实现不同,分布式命令总线根本不调用任何处理程序。 它们所做的只是在不同 JVM 上的命令总线实现之间形成 "bridge",将任何接收到的命令委托给所谓的本地段。

默认情况下,此本地段是 SimpleCommandBus。 您也可以将本地段配置为任何其他本地命令总线,例如 AsynchronousCommandBusDisruptorCommandBus。 如何配置本地段的详细信息显示在实现部分中。

负载系数

负载系数定义了 Axon 应用程序与其他实例相比将承载的负载量。 例如,如果您设置了两台机器,每台机器的负载系数为 100,它们都将承载相同数量的负载。

将两者的负载系数增加到 200 仍然意味着两台机器接收相同数量的负载。 这指出负载系数只会在值不相等时改变系统之间的负载。 这样做在异构应用程序环境中是有意义的,在这种环境中,速度较快的机器应该比速度较慢的机器处理更大的命令处理部分。

为分布式 CommandBus 实现设置的默认负载系数为 100。每个分布式实现的配置略有变化,因此将在这些部分中介绍。

路由策略

命令应该一致地路由到同一个应用程序,尤其是那些针对特定聚合的应用程序。 这确保了单个实例负责目标聚合,解决并发访问问题并允许缓存等优化按设计工作。 在 Axon 应用程序中处理一致路由的组件是 RoutingStrategy

RoutingStrategy 接收一个 CommandMessage 并根据该消息返回要使用的路由键。 只要分布式设置中没有拓扑变化,具有相同路由键的两个命令将始终路由到同一段。

目前,RoutingStrategy 有五种实现。 其中三个旨在作为备用解决方案,以防路由键无法解析:

  1. AnnotationRoutingStrategy - 默认路由策略期望 TargetAggregateIdentifierRoutingKey 注解出现在命令类内的字段上。 搜索带注解的字段或 getter,其内容将作为该命令的路由键返回。
  2. MetaDataRoutingStrategy - 使用在创建此策略期间定义的属性从 CommandMessageMetaData 中获取路由键。
  3. ERROR UnresolvedRoutingKeyPolicy -当无法从给定的 CommandMessage 解析路由键时,将导致引发异常的默认回退
  4. RANDOM_KEY UnresolvedRoutingKeyPolicy - 当无法从 CommandMessage 解析路由键时,将返回一个随机值。 这意味着这些命令将被路由到命令总线的随机段。
  5. STATIC_KEY UnresolvedRoutingKeyPolicy - 将为未解析的路由键返回一个静态键(名为 "unresolved")。 该策略将所有命令路由到同一段,只要段的配置不变。

AnnotationRoutingStrategyMetaDataRoutingStrategy 被认为是要配置的完整实现。 ERRORRANDOM_KEYSTATIC_KEY 是备用路由策略,应该在注解或元数据实现上配置。 要了解这些是如何构建的,请参考以下示例:

AnnotationRoutingStrategy

// 自定义注解可用于驱动 AnnotationRoutingStrategy
@interface CustomRoutingAnnotation {
}
// 构造一个带有不同注解和回退的 AnnotationRoutingStrategy:
public RoutingStrategy routingStrategy() {
    return AnnotationRoutingStrategy.builder()
                                    .annotationType(CustomRoutingAnnotation.class)
                                    .fallbackRoutingStrategy(UnresolvedRoutingKeyPolicy.STATIC_KEY)
                                    .build();
}

MetaDataRoutingStrategy

// 使用定义的元数据键和不同的回退构造一个 MetaDataRoutingStrategy:
public RoutingStrategy routingStrategy() {
    return MetaDataRoutingStrategy.builder()
                                  .metaDataKey("my-routing-key")
                                  .fallbackRoutingStrategy(UnresolvedRoutingKeyPolicy.RANDOM_KEY)
                                  .build();
}

当然,必要时也可以提供 RoutingStrategy 的自定义实现。 当我们需要偏离默认的 AnnotationRoutingStrategy 时,我们应该像这样配置它:

Axon 配置 API

public class AxonConfig {
    // ...
    public void configureRoutingStrategy(Configurer configurer, YourRoutingStrategy yourRoutingStrategy) {
        configurer.registerComponent(RoutingStrategy.class, config -> yourRoutingStrategy);
    }
}

Spring Boot AutoConfiguration

@Configuration
public class AxonConfig {
    // ...
    @Bean
    public RoutingStrategy routingStrategy() {
        return /* construct your routing strategy */;
    }
}

AxonServerCommandBus

AxonServerCommandBus 是框架设置的默认分布式 CommandBus 实现。 它连接到 AxonServer,通过它可以发送和接收命令。

由于它是默认设置,因此配置它相对简单:

Axon Configuration API

声明依赖:

<!-- somewhere in the POM file... -->
<dependencyManagement>
    <!-- amongst the dependencies... -->
    <dependencies>
        <dependency>
            <groupId>org.axonframework</groupId>
            <artifactId>axon-bom</artifactId>
            <version>${version.axon}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
    <!-- ... -->
</dependencyManagement>
<!-- ... -->
<dependencies>
    <!-- amongst the dependencies... -->
    <dependency>
        <groupId>org.axonframework</groupId>
        <artifactId>axon-server-connector</artifactId>
    </dependency>
    <dependency>
        <groupId>org.axonframework</groupId>
        <artifactId>axon-configuration</artifactId>
    </dependency>
    <!-- ... -->
</dependencies>

配置您的应用程序:

// AxonServerCommandBus 在构造 DefaultConfigurer 时默认配置为 Command Bus。
Configurer configurer = DefaultConfigurer.defaultConfiguration();

Spring Boot AutoConfiguration

通过简单地包含 axon-spring-boot-starter 依赖,Axon 将自动配置 AxonServerCommandBus

<!--somewhere in the POM file-->
<dependency>
    <groupId>org.axonframework</groupId>
    <artifactId>axon-spring-boot-starter</artifactId>
    <version>${axon.version}</version>
</dependency>

禁用 Axon Server

有两个选项可以禁用 Axon Framework 默认使用 AxonServerCommandBus

  1. 通过排除 axon-server-connector 依赖。
  2. 通过在使用 Spring Boot 时将 axon.server.enabled 设置为 false

当执行任何这些操作时,Axon 将回退到未分发的 SimpleCommandBus,除非另有配置。

本地段和负载系数配置

AxonServerCommandBus 的负载系数是通过 CommandLoadFactorProvider 定义的。 该接口允许我们区分命令,例如,每个命令消息使用不同的负载系数。 如果某些命令更频繁地被路由到一个实例而不是另一个实例,这可能很有用。

应执行以下操作来配置自定义本地段和/或负载系数:

Axon Configuration API

// 在配置类的某处
public CommandBus axonServerCommandBus(CommandBus localSegment,
                                       CommandLoadFactorProvider loadFactorProvider,
                                       ...) {
    return AxonServerCommandBus.builder()
                               .localSegment(localSegment)
                               .targetContextResolver(targetContextResolver)
                               // 所有必需的配置组件都在 Builder 的 JavaDoc 中指定
                               .build();
}

Spring Boot AutoConfiguration

@Configuration
public class AxonConfig {
    // 指定 “localSegment” 的限定符注解将使此 CommandBus 成为本地段
    @Bean
    @Qualifier("localSegment")
    public CommandBus localSegment() {

        return /* construct your local segment */;
    }

    @Bean
    public CommandLoadFactorProvider loadFactorProvider() {
      return /* construct your load factor provider */;
    }
}

DistributedCommandBus

AxonServerCommandBus 的替代方案是 DistributedCommandBus。 每个 JVM 上的每个 DistributedCommandBus 实例称为一个 "Segment"。

Figure 1. 分布式命令总线的结构

DistributedCommandBus 依赖于两个组件:

  1. CommandBusConnector - 实现 JVM 之间的通信协议,以通过线路发送命令并接收响应。
  2. CommandRouter - 为每个传入命令选择目的地。 它根据路由策略计算的路由键定义应向 DistributedCommandBus 的哪个 segment 发出命令。

您可以选择这些组件的不同风格,这些组件可用作扩展模块。 目前,Axon 为此提供了两个扩展,它们是:

  1. SpringCloud 扩展
  2. JGroups 扩展

可以(大部分)配置分布式命令总线,而无需对配置文件进行任何修改。 最直接的方法是包含 Spring Cloud 或 JGroups 扩展的 Spring Boot Starter 依赖。 有了这些,需要将一个属性添加到应用程序上下文中,以启用 DistributedCommandBus

axon.distributed.enabled=true

建议访问相应的扩展篇,了解如何为 DistributedCommandBus 配置 JGroups 或 Spring Cloud。

相关推荐

好用的云函数!后端低代码接口开发,零基础编写API接口

前言在开发项目过程中,经常需要用到API接口,实现对数据库的CURD等操作。不管你是专业的PHP开发工程师,还是客户端开发工程师,或者是不懂编程但懂得数据库SQL查询,又或者是完全不太懂技术的人,通过...

快速上手:Windows 平台上 cURL 命令的使用方法

在工作流程中,为了快速验证API接口有效性,团队成员经常转向直接执行cURL命令的方法。这种做法不仅节省时间,而且促进了团队效率的提升。对于使用Windows系统的用户来说,这里有一套详细...

使用 Golang net/http 包:基础入门与实战

简介Go的net/http包是构建HTTP服务的核心库,功能强大且易于使用。它提供了基本的HTTP客户端和服务端支持,可以快速构建RESTAPI、Web应用等服务。本文将介绍ne...

#小白接口# 使用云函数,人人都能编写和发布自己的API接口

你只需编写简单的云函数,就可以实现自己的业务逻辑,发布后就可以生成自己的接口给客户端调用。果创云支持对云函数进行在线接口编程,进入开放平台我的接口-在线接口编程,设计一个新接口,设计和配置好接口参...

极度精神分裂:我家没有墙面开关,但我虚拟出来了一系列开关

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:iN在之前和大家说过,在iN的家里是没有墙面开关的。...

window使用curl命令的注意事项 curl命令用法

cmd-使用curl命令的注意点前言最近在cmd中使用curl命令来测试restapi,发现有不少问题,这里记录一下。在cmd中使用curl命令的注意事项json不能由单引号包括起来json...

Linux 系统curl命令使用详解 linuxctrl

curl是一个强大的命令行工具,用于在Linux系统中进行数据传输。它支持多种协议,包括HTTP、HTTPS、FTP等,用于下载或上传数据,执行Web请求等。curl命令的常见用法和解...

Tornado 入门:初学者指南 tornados

Tornado是一个功能强大的PythonWeb框架和异步网络库。它最初是为了处理实时Web服务中的数千个同时连接而开发的。它独特的Web服务器和框架功能组合使其成为开发高性能Web...

PHP Curl的简单使用 php curl formdata

本文写给刚入PHP坑不久的新手们,作为工具文档,方便用时查阅。CURL是一个非常强大的开源库,它支持很多种协议,例如,HTTP、HTTPS、FTP、TELENT等。日常开发中,我们经常会需要用到cur...

Rust 服务器、服务和应用程序:7 Rust 中的服务器端 Web 应用简介

本章涵盖使用Actix提供静态网页...

我给 Apache 顶级项目提了个 Bug apache顶级项目有哪些

这篇文章记录了给Apache顶级项目-分库分表中间件ShardingSphere提交Bug的历程。说实话,这是一次比较曲折的Bug跟踪之旅。10月28日,我们在GitHub上提...

linux文件下载、服务器交互(curl)

基础环境curl命令描述...

curl简单使用 curl sh

1.curl--help#查看关键字2.curl-A“(添加user-agent<name>SendUser-Agent<name>toserver)”...

常用linux命令:curl 常用linux命令大全

//获取网页内容//不加任何选项使用curl时,默认会发送GET请求来获取内容到标准输出$curlhttp://www.baidu.com//输出<!DOCTYPEh...

三十七,Web渗透提高班之hack the box在线靶场注册及入门知识

一.注册hacktheboxHackTheBox是一个在线平台,允许测试您的渗透技能和代码,并与其他类似兴趣的成员交流想法和方法。它包含一些不断更新的挑战,并且模拟真实场景,其风格更倾向于CT...