通过将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
<b>public</b> <b>class</b> StateMachineConfig <b>extends</b> EnumStateMachineConfigurerAdapter<States, Events> {...}
下一个要做的事情是配置状态,事件 -启动状态转换的触发器,以及在动作处理期间触发的转换动作,您可以阅读 本章 有关配置类内部的内容:
@Override
<b>public</b> <b>void</b> 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
<b>public</b> StateMachineEnsemble<States, Events> stateMachineEnsemble() throws Exception {
<b>return</b> <b>new</b> ZookeeperStateMachineEnsemble<States, Events>(curatorClient(), <font>"/zkPath"</font><font>); }
</font>
stateMachineEnsemble bean很快会在最后一步中用于声明分布式状态机。
创建CuratorFramework实例时,应知道托管Apache Zookeeper二进制文件的计算机的IP /主机名。将docker-compose用作编排工具,以便将定位Apache Zookeeper的计算机的主机名作为环境变量传递。除此之外,将使用Zookeeper默认端口2181,如下:
@Bean
<b>public</b> CuratorFramework curatorClient() throws Exception {
String zkConnectionString = <font>"zookeeper:2181"</font><font>;
RetryPolicy retryPolicy = <b>new</b> ExponentialBackoffRetry(1000, 3);
CuratorFramework client = CuratorFrameworkFactory.builder()
.defaultData(<b>new</b> byte[0])
.retryPolicy(retryPolicy)
.connectString(zkConnectionString)
.build();
client.start();
CuratorFrameworkState state = client.getState();
System.out.println(</font><font>"State ----> "</font><font> + state.name());
<b>return</b> client;
}
</font>
下面是最后一步,使用如上所述注入的stateMachineEnsemble bean 声明分布式状态机:
@Override
<b>public</b> <b>void</b> configure(StateMachineConfigurationConfigurer
<States, Events> config) throws Exception {
config
.withDistributed()
.ensemble(stateMachineEnsemble());
}
当zookeeper和statemachines连接时,Z序节点可以或者与查询内置zookeeper命令或CuratorFramework内置的方法:
实现的细节见 此 链接,整个项目在 此 。