AxonFramework,分佈式命令總線連接器

JGroupsConnector
JGroupsConnector使用(正如它的名字已經說明)JGroups作爲底層發現和調度機制。描述JGroups的特性有太多的參考指南,請參閱JGroups用戶指南以瞭解更多的細節。

因爲JGroups既處理節點的發現又處理它們之間的通信,所以JGroupsConnector既充當CommandBusConnector也充當CommandRouter。

注意
你可以在axon-distributed-commandbus-jgroups模塊中,爲DistributedCommandBus找到JGroups特定組件。

JGroupsConnector有四個強制性配置元素:

  • 第一種是JChannel,它定義了JGroups協議棧。一般來說,用JGroups配置文件的引用構造JChannel。JGroups附帶的默認配置,可以用作自己配置的依據。請記住,IP多路廣播一般不工作在雲服務中,像亞馬遜。中這種類型的環境中, TCP Gossip通常是一個好的開端。
  • 集羣名稱定義了每個segment應登記到的集羣的名稱。具有相同的集羣名稱的Segment最終會探測到彼此,並在彼此間分發命令。
  • “本地segment”是命令總線實現,分發命令去往本地的JVM。這些命令可能已通過其他JVM或從本地的一個實例分發。
  • 最後,序列化器是用來序列化之前通過線路發送的命令消息。

注意
當使用緩存時,當ConsistentHash更改以避免潛在的數據損壞時,它應該被清空(例如,當命令沒有指定一個@TargetAggregateVersion和新成員快速加入和離開JGroup,修改聚合然而它還要緩存到其他地方)。

最終,JGroupsConnector需要實際連接,按順序分發消息到其他segment。這樣做,調用connect()方法。

JChannel channel = new JChannel("path/to/channel/config.xml");
CommandBus localSegment = new SimpleCommandBus();
Serializer serializer = new XStreamSerializer();

JGroupsConnector connector = new JGroupsConnector(channel, "myCommandBus", localSegment, serializer);
DistributedCommandBus commandBus = new DistributedCommandBus(connector, connector);

// on one node:
commandBus.subscribe(CommandType.class.getName(), handler);
connector.connect();

// on another node, with more CPU:
commandBus.subscribe(CommandType.class.getName(), handler);
commandBus.subscribe(AnotherCommandType.class.getName(), handler2);
commandBus.updateLoadFactor(150); // defaults to 100
connector.connect();

// from now on, just deal with commandBus as if it is local...

注意
注意,並非所有的segment都必需具有相同類型的命令的命令處理器。你完全可以爲不同的命令類型使用不同的segment。分佈式命令總線總是選擇一個節點分發命令到那個支持特定類型的命令。

如果你使用Spring,你可能需要考慮使用JGroupsConnectorFactoryBean。它自動連接連接器當ApplicationContext啓動後,並且在ApplicationContext關閉時完全的斷開。此外,它爲測試環境使用合理的默認值(但不應被視爲生產準備)和自動裝配配置。

Spring Cloud Connector

Spring Cloud連接器裝置,用Spring Cloud來描述使用服務註冊和發現機制來分配命令總線。因此,你可以自由選擇使用哪一個Spring Cloud實現用來分發你的命令。實現的一個例子是 Eureka Discovery/Eureka 服務器組合。

注意
當前版本(Axon 3.0.4)SpringCloudCommandRouter使用ServiceInstance。Metadata 字段來通知所有系統中的節點,通過CommandNameFilter它可以處理命令。這是很重要的,Spring Cloud實現選擇支持ServiceInstance.Metadata字段的使用。例如Spring Cloud Consul目前不支持該字段,因此SpringCloudCommandRouter並不是一個可行的解決方案。我們正在研究一個額外的解決方案,從中檢索CommandNameFilter 。

提供每個SpringCloud實現的描述將推動本參考指南。因此,我們參考他們各自的文件以獲得進一步的信息。

Spring Cloud連接器裝置是一個SpringCloudCommandRouter和SpringHttpCommandBusConnector的組合,分別填充CommandRouter的地點和 DistributedCommandBus的CommandBusConnector。

注意
Spring Cloud連接器特定的組件DistributedCommandBus可以在axon-distributed-commandbus-springcloud模塊中找到 。

SpringCloudCommandRouter必須由以下提供的來創建:
* 一個DiscoveryClient類型“discovery client”。這可以通過用@EnableDiscoveryClient註解你的Spring Boot應用程序來提供,將在你的類路徑中尋找Spring Cloud 的實現。
* 一個RoutingStrategy類型的”routing strategy”。目前axon-core模塊提供了一些實現,但是一函數調用也可以滿足要求。例如,如果你想路由命令基於“聚合標識符”,你可以使用AnnotationRoutingStrategy和註解有效載荷的字段,用@TargetAggregateIdentifier識別聚合。

SpringHttpCommandBusConnector需要創建三個參數:

  • 一個CommandBus類型的“local command bus”。這是命令總線實現,它將分發命令到本地的JVM。這些命令可能是由其他JVM上的或本地的實例分發。
  • RestOperations對象來執行一個命令消息的發佈到另一個實例。
  • 最後一個Serializer類型的“序列serializer”。序列化器用於在命令發送到網絡之前序列化命令消息。

SpringCloudCommandRouter和SpringHttpCommandBusConnector應該都被用於創建DistributedCommandsBus。在Spring Java 配置中,看起來如下:

// Simple Spring Boot App providing the `DiscoveryClient` bean
@EnableDiscoveryClient
@SpringBootApplication
public class MyApplication {

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

    // Example function providing a Spring Cloud Connector
    @Bean
    public CommandRouter springCloudCommandRouter(DiscoveryClient discoveryClient) {
        return new SpringCloudCommandRouter(discoveryClient, new AnnotationRoutingStrategy());
    }

    @Bean
    public CommandBusConnector springHttpCommandBusConnector(@Qualifier("localSegment") CommandBus localSegment,
                                                             RestOperations restOperations,
                                                             Serializer serializer) {
        return new SpringHttpCommandBusConnector(localSegment, restOperations, serializer);
    }

    @Primary // to make sure this CommandBus implementation is used for autowiring
    @Bean
    public DistributedCommandBus springCloudDistributedCommandBus(CommandRouter commandRouter, 
                                                                  CommandBusConnector commandBusConnector) {
        return new DistributedCommandBus(commandRouter, commandBusConnector);
    }

}

// if you don't use Spring Boot Autoconfiguration, you will need to explicitly define the local segment:
@Bean
@Qualifier("localSegment")
public CommandBus localSegment() {
    return new SimpleCommandBus();
}

注意
注意,並非所有的segment都必需具有相同類型的命令的命令處理器。你完全可以爲不同的命令類型使用不同的segment。分佈式命令總線總是選擇一個節點分發命令到那個支持特定類型的命令。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章