通过将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内置的方法:
实现的细节见 此 链接,整个项目在 此 。