使用Spring Boot、Spring State Machine Framework和Zookeeper構建分散式狀態機 - ÖzdinçÇelikel

banq發表於2020-01-07

通過將Apache Zookeeper與Java Spring State Machine框架整合在一起,為構建分散式狀態機提供一個框架。

所謂Java Spring State Machine框架:應用程式現在處於並且可能以有限數量的狀態存在。然後會發生一些事情,將您的應用程式從一種狀態轉移到另一種狀態。狀態機由觸發器驅動,觸發器基於事件或計時器。

狀態機的分散式屬性在預設狀態機實現的基礎上帶有一個抽象層,目前僅存在一個基於Apache Zookeeper的實現,Apache Zookeeper是一種分散式應用程式的 協調服務。我的建議是在深入瞭解之前,通過此連結閱讀官方的Spring State Machine文件。

對於此示例,狀態機將具有3個狀態:

UNPARID --->PAY事件--->WAITING --->RECEIVE事件 --->DONE

為了使用Spring Boot狀態機框架,將使用maven將所需的依賴項注入到專案結構中:

<dependency> 
<groupId>org.springframework.statemachine </ groupId> 
<artifactId>spring-statemachine-core </ artifactId> 
<version>2.1.3.RELEASE </ version> 
</dependency>

匯入此依賴項後,不要忘記乾淨的target /目錄,再次將專案檔案安裝到本地儲存庫,並通過以下maven命令在target /目錄下生成類:

mvn clean && mvn install && mvn complie

在此示例中,有4個容器是狀態機的主機。這些容器將通過docker-compose進行編排。其中三個容器將執行相同的分散式狀態機,其餘的將作為Apache Zookeeper二進位制檔案的主機。在每個容器中執行狀態機時,它們都將使用相同的Apache Zookeeper例項-znode-進行分發。因此,通過使用Apache Zookeeper建立狀態機的分散式屬性。Spring還有一個很好的例子來理解這種用法​​。

首先,需要一個Spring Configuration類,該類帶有@Configuration註釋,並充當bean定義的容器。

@Configuration                       
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<States, Events> {...}

下一個要做的事情是配置狀態,事件 -啟動狀態轉換的觸發器,以及在動作處理期間觸發的轉換動作,您可以閱讀本章 有關配置類內部的內容:

@Override
public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
        throws Exception {
            transitions
            .withExternal()
            .source(States.UNPAID).
             target(States.WAITING_FOR_RECEIVE)
            .event(Events.PAY)
            .action(transitionAction())
            
            .and()
            
            .withExternal()
            .source(States.WAITING_FOR_RECEIVE)
            .target(States.DONE)
            .event(Events.RECEIVE)
            .action(transitionAction())
            
            .and()
            
            .withExternal()
            .source(States.DONE).target(States.UNPAID)
            .event(Events.STARTFROMSCRATCH)
            .action(transitionAction());
}

在Configuration類內部,需要通過傳遞curotorClient來例項化集合,curotorClient是用於簡化Zookeeper功能的使用的API,並且basePath指示基本的Zookeeper 路徑,將用於建立znodes,強烈建議您依次閱讀官方文件習慣術語。

@Bean                           
public StateMachineEnsemble<States, Events> stateMachineEnsemble() throws Exception {                                              
return new ZookeeperStateMachineEnsemble<States, Events>(curatorClient(), "/zkPath");                           }

stateMachineEnsemble bean很快會在最後一步中用於宣告分散式狀態機。

建立CuratorFramework例項時,應知道託管Apache Zookeeper二進位制檔案的計算機的IP /主機名。將docker-compose用作編排工具,以便將定位Apache Zookeeper的計算機的主機名作為環境變數傳遞。除此之外,將使用Zookeeper預設埠2181,如下:

@Bean                           
public CuratorFramework curatorClient() throws Exception {
      String zkConnectionString = "zookeeper:2181";  
      RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
       CuratorFramework client = CuratorFrameworkFactory.builder()
                                      .defaultData(new byte[0])
                                      .retryPolicy(retryPolicy)
                                      .connectString(zkConnectionString)
                                      .build();                              
      client.start();                               
      CuratorFrameworkState state = client.getState();                                    
      System.out.println("State ----> " + state.name());                               
      return client;                           
}

下面是最後一步,使用如上所述注入的stateMachineEnsemble bean 宣告分散式狀態機:

@Override                           
public void configure(StateMachineConfigurationConfigurer
<States, Events> config) throws Exception {
config                                       
 .withDistributed()
 .ensemble(stateMachineEnsemble());
}

當zookeeper和statemachines連線時,Z序節點可以或者與查詢內建zookeeper命令或CuratorFramework內建的方法:

實現的細節見連結,整個專案在

 

相關文章