Axon 参考指南
  • 介绍
  • 架构概览
    • DDD & CQRS 概念
    • 事件溯源
    • 事件驱动的微服务
  • Axon Server
  • 发行说明
    • Axon Framework
      • Major Releases
      • Minor Releases
    • Axon Server
      • Major Releases
      • Minor Releases Standard Edition
      • Minor Releases Enterprise Edition
    • Axon Framework Extensions
      • AMQP
        • Major Releases
      • CDI
        • Major Releases
      • JGroups
        • Major Releases
      • Kafka
        • Major Releases
        • Minor Releases
      • Kotlin
        • Experimental Releases
      • Mongo
        • Major Releases
        • Minor Releases
      • Reactor
        • Major Releases
        • Minor Releases
      • Spring Cloud
        • Major Releases
        • Minor Releases
      • Tracing
        • Major Releases
        • Minor Releases
  • Getting Started
    • 快速开始
  • Axon Framework
    • 介绍
    • 消息传递概念
      • 消息剖析
      • 消息关联
      • 消息拦截
      • 支持带注解的处理程序
      • 异常处理
      • 工作单元
    • 命令
      • 建模
        • 聚合
        • 多实体聚合
        • 聚合状态存储
        • 从另一个聚合创建聚合
        • 聚合多态性
        • 解决冲突
      • 命令调度器
      • 命令处理程序
      • 基础设施
      • 配置
    • 事件
      • 事件调度器
      • 事件处理程序
      • 事件处理器
        • 订阅事件处理器
        • 流式事件处理器
      • 事件总线和事件存储
      • 事件版本控制
    • 查询
      • 查询处理
      • 查询调度器
      • 查询处理程序
      • 实现
      • 配置
    • 长时处理过程(Sagas)
      • 实现
      • 关联
      • 基础设施
    • Deadlines
      • Deadline Managers
      • Event Schedulers
    • 测试
      • 命令 / 事件
      • 长时处理过程(Sagas)
    • 序列化
    • 调整
      • 事件快照
      • 事件处理
      • 命令处理
    • 监控和指标
    • Spring Boot 集成
    • 模块
  • Axon Server
    • 介绍
    • 安装
      • 本地安装
        • Axon Server SE
        • Axon Server EE
      • Docker / K8s
        • Axon Server SE
        • Axon Server EE
    • 管理
      • 配置
        • System Properties
        • Command Line Interface
        • REST API
        • GRPC API
      • Monitoring
        • Actuator Endpoints
        • gRPC Metrics
        • Heartbeat Monitoring
      • Clusters
      • Replication Groups
      • Multi-Context
      • Tagging
      • Backup and Messaging-only Nodes
      • Backups
      • Recovery
      • Plugins
      • Error Codes
    • 安全
      • SSL
      • 访问控制
      • 访问控制 - 标准版
      • 访问控制 - 企业版
      • 访问控制 - 客户端应用程序
      • 访问控制 - 命令行
      • 访问控制 - REST API
      • 访问控制 - LDAP
      • 访问控制 - OAuth 2.0
    • 性能
      • 事件段
      • 流量控制
    • 迁移
      • Standard to Enterprise Edition
      • Non-Axon Server to Axon Server
  • Extensions
    • Spring AMQP
    • JGroups
    • Kafka
    • Kotlin
    • Mongo
    • Reactor
      • Reactor Gateways
    • Spring Cloud
    • Tracing
  • Appendices
    • A. RDBMS Tuning
    • B. Message Handler Tuning
      • 参数解析器
      • 处理程序增强
    • C. 元数据注解
    • D. 标识符生成
    • E. Axon Server Query Language
由 GitBook 提供支持
在本页
  • Discovering Command Routes
  • Sending Commands between nodes
  • Configuring this Extension
  1. Extensions

Spring Cloud

上一页Reactor Gateways下一页Tracing

最后更新于2年前

Spring Cloud is an alternative approach to distributing the command bus (commands), besides Axon Server as the default.

The Spring Cloud Extension uses the service registration and discovery mechanism described by for distributing the command bus. You thus have the choice of which Spring Cloud implementation to use when discovering the routes to distribute your commands. An example of that would be Netflix' combination or HashiCorp's .

To use the Spring Cloud components from Axon, make sure the axon-springcloud module is available on the classpath. The easiest way is to include the Spring Cloud starter (axon-springcloud-spring-boot-starter) from this extension to your project.

Giving a description of every Spring Cloud implementation would push this reference guide too far. For information on other Spring Cloud implementation options out there, please refer to their respective documentations.

The Spring Cloud connector setup is a combination of the SpringCloudCommandRouter and a SpringHttpCommandBusConnector. The former is the CommandRouter and latter the CommandBusConnector, both used by the DistributedCommandBus to enable command distribution.

Discovering Command Routes

The SpringCloudCommandRouter uses Spring Cloud's discovery mechanism to find the other nodes in the cluster. To that end it uses the DiscoveryClient and Registration from Spring Cloud. These are respectively used to gather remote command routing information and maintain local information. The most straightforward way to retrieve both is by annotating your application with @EnableDiscoveryClient.

Gathering and storing the command routing information revolves around Spring Cloud's ServiceInstances. A Registration is just the local ServiceInstance, whereas the DiscoveryClient provides the API to find remote ServiceInstances. Furthermore, it is the ServiceInstance which provides us with the required information (e.g. the URI) to retrieve a node's capabilities.

Spring Cloud's Heartbeat Requirement

When using the SpringCloudCommandRouter, make sure your Spring application has heartbeat events enabled. The heartbeat events published by a Spring Cloud application are the trigger to check if the set of ServiceInstances from the DiscoveryClient has been changed. Additionally, it is used to validate whether the command routing capabilities for known nodes has been altered.

Thus, if heartbeat events are disabled, your instance will no longer be updated with the current command routing capabilities. If so, this will cause issues during command routing.

The logic to store the local capabilities and discovering the remote capabilities of a ServiceInstance is maintained in the CapabilityDiscoveryMode. It is thus the CapabilityDiscoveryMode which provides us the means to actually retrieve a ServiceInstance's set of commands it can handle (if any). The sole full implementation provided of the CapabilityDiscoveryMode, is the RestCapabilityDiscoveryMode, using a RestTemplate and the ServiceInstance URI to invoke a configurable endpoint. This endpoint leads to the MemberCapabilitiesController which in turn exposes the MemberCapabilities on the RestCapabilityDiscoveryMode of that instance.

There are decorators present for the CapabilityDiscoveryMode, providing two additional features:

  1. IgnoreListingDiscoveryMode - a CapabilityDiscoveryMode decorator which on failure of retrieving the MemberCapabilities will place the given ServiceInstance on a list to be ignored for future validation. It thus effectively removes discoverable ServiceInstances from the set.

  2. AcceptAllCommandsDiscoveryMode - a CapabilityDiscoveryMode decorator which regardless of what this instance can handle as commands, state it can handle anything. This decorator comes in handy if the nodes in the system are homogeneous (aka, everybody can handle the same set of commands).

The Registration, DiscoveryClient and CapabilityDiscoveryMode are arguably the heart of the SpringCloudCommandRouter. There are, however, a couple of additional things you can configure for this router, which are the following:

  • A ServiceInstance filter - This Predicate is used to filter out ServiceInstances retrieved through the DiscoveryClient. For example, it allows the removal of instances which are known to not handle any command messages. This might be useful if you have several services within the Spring Cloud Discovery Service set up, which you do not ever want to take into account for command handling.

  • ConsistentHashChangeListener - Adding a consistent hash change listener provides you with the opportunity to perform a specific task if new nodes have been added to the known command handlers set.

Differing Command Capabilities per Node

It is not required for all nodes to have the same set of command handlers. You may use different segments for different command types altogether. The Distributed Command Bus will always choose a node to dispatch a command to the one that has support for that specific type of command.

Sending Commands between nodes

The CommandBusConnector is in charge of sending commands, based on a given route, from one node to another. This extension to that end provides the SpringHttpCommandBusConnector, which uses plain REST for sending commands.

There are three hard requirements when creating this service and one optional configuration:

  1. Local CommandBus - This "local segment" is the command bus which dispatches commands into the local JVM. It is thus invoked when the SpringHttpCommandBusConnector receives a command from the outside, or if it receives a command which is meant for itself.

  2. RestOperations - The service used to POST a command message to another instance. In most situations the RestTemplate is used for this.

  3. Serializer - The serializer is used to serialize the command messages before they are sent over and deserialize when they are received.

  4. Executor (optional) - The Executor is used to handle incoming commands and to dispatch commands. Defaults to a DirectExecutor instance.

Configuring this Extension

Chances are high that you will be using Spring Boot if you are also using Spring Cloud. As configuring goes, this would opt for usage of the axon-springcloud-spring-boot-starter dependency to automatically retrieve all required beans. In either case, your application should be marked to enable it as a discoverable service through Spring Cloud. This can, for example, be done by annotating the main class with @EnableDiscoveryClient.

There are still quite a few customizable components. For some suggestions, take a look at the following examples:

// Custom Spring Boot app, enabling a 'DiscoveryClient' and 'Registration' through `@EnableDiscoveryClient`
@EnableDiscoveryClient
@SpringBootApplication
public class MyApplication {

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public CapabilityDiscoveryMode capabilityDiscoveryMode(RestTemplate restTemplate, Serializer serializer) {
        return RestCapabilityDiscoveryMode.builder()
                                          .restTemplate(restTemplate)
                                          .serializer(serializer)
                                          // Allows changing the endpoint used to find member capabilities
                                          .messageCapabilitiesEndpoint(/* custom message information endpoint */)
                                          .build();
    }

    @Bean
    public CommandRouter springCloudCommandRouter(DiscoveryClient discoveryClient,
                                                  Registration localServiceInstance,
                                                  CapabilityDiscoveryMode capabilityDiscoveryMode) {
        return SpringCloudCommandRouter.builder()
                                       .discoveryClient(discoveryClient)
                                       .routingStrategy(new AnnotationRoutingStrategy())
                                       .localServiceInstance(localServiceInstance)
                                       .capabilityDiscoveryMode(capabilityDiscoveryMode)
                                       .serviceInstanceFilter(/* custom ServiceInstance filter */)
                                       .consistentHashChangeListener(/* ConsistentHash change listener */)
                                       .build();
    }

    // Only required if Axon Spring Boot Starter is not used
    @Bean
    @Qualifier("localSegment")
    public CommandBus localSegment() {
        return SimpleCommandBus.builder().build();
    }

    @Bean
    public CommandBusConnector springHttpCommandBusConnector(@Qualifier("localSegment") CommandBus localSegment,
                                                             RestOperations restOperations,
                                                             Serializer serializer) {
        return SpringHttpCommandBusConnector.builder()
                                            .localCommandBus(localSegment)
                                            .restOperations(restOperations)
                                            .serializer(serializer)
                                            .executor(/* custom Executor */)
                                            .build();
    }

    @Bean
    @Primary
    public DistributedCommandBus distributedCommandBus(CommandRouter commandRouter,
                                                       CommandBusConnector commandBusConnector) {
        return DistributedCommandBus.builder()
                                    .commandRouter(commandRouter)
                                    .connector(commandBusConnector)
                                    .build();
    }
}
# Required to enabled the DistributedCommandBus
axon.distributed.enabled=true
# Defines the load factor used for this segment. Defaults to 100
axon.distributed.load-factor=100
# Defines the CapabilityDiscoveryMode used. Defaults to REST
axon.distributed.spring-cloud.mode=rest
# Defines the endpoint used to retrieve member capabilities from. Defaults to "/member-capabilities"
axon.distributed.spring-cloud.rest-mode-url="/my-custom-endpoint"
# Defines whether the CapabilityDiscoveryMode should be decorated to ignore faulty ServiceInstances 
axon.distributed.spring-cloud.enable-ignore-listing=true
# Defines whether the CapabilityDiscoveryMode should be decorated to accept all types of commands
axon.distributed.spring-cloud.enable-accept-all-commands=true

RoutingStrategy - The component in charge of deciding which of the nodes receives the commands consistently. By default, a AnnotationRoutingStrategy is used (see for more).

Spring Cloud
Eureka Discovery/Eureka Server
Consul
Distributing the Command Bus