31. Using Distributed States
分布式状态可能是Spring State Machine最复杂的概念之一。 什么是分布式状态? 单个状态机内的状态自然很容易理解,但是当需要通过状态机引入共享分布式状态时,事情会变得复杂一些。
分布式状态功能仍然是预览功能,在这个特定版本中尚未被认为是稳定的。 我们预计这个功能会朝着第一次正式发布的方向发展。
有关通用配置支持,请参见第11.9节“配置通用设置”和实际使用示例,请参阅第43章Zookeeper示例。
分布式状态机是通过一个DistributedStateMachine类来实现的,该类简单地包装了一个StateMachine的实际实例。 DistributedStateMachine拦截与StateMachine实例的通信,并使用通过接口StateMachineEnsemble处理的分布式状态抽象。 根据实际的实现情况,StateMachinePersist接口也可以用来序列化一个StateMachineContext,它包含足够的信息来重置一个StateMachine。
虽然分布式状态机是通过抽象实现的,但基于Zookeeper,当前只存在一个实现。
这是一个基于Zookeeper的分布式状态机的配置示例。
@Configuration
@EnableStateMachine
public class Config
extends StateMachineConfigurerAdapter<String, String> {
@Override
public void configure(StateMachineConfigurationConfigurer<String, String> config)
throws Exception {
config
.withDistributed()
.ensemble(stateMachineEnsemble())
.and()
.withConfiguration()
.autoStartup(true);
}
@Override
public void configure(StateMachineStateConfigurer<String, String> states)
throws Exception {
// config states
}
@Override
public void configure(StateMachineTransitionConfigurer<String, String> transitions)
throws Exception {
// config transitions
}
@Bean
public StateMachineEnsemble<String, String> stateMachineEnsemble()
throws Exception {
return new ZookeeperStateMachineEnsemble<String, String>(curatorClient(), "/zkpath");
}
@Bean
public CuratorFramework curatorClient()
throws Exception {
CuratorFramework client = CuratorFrameworkFactory
.builder()
.defaultData(new byte[0])
.connectString("localhost:2181").build();
client.start();
return client;
}
}
基于Zookeeker的分布式状态机的当前技术文档可以从附录C的“分布式状态机技术文档”中找到。
31.1 ZookeeperStateMachineEnsemble
ZookeeperStateMachineEnsemble本身需要两个强制设置,curatorClient和basePath的一个实例。 客户端是CuratorFramework,路径是Zookeeper中树的根。
可选地,可以设置默认为TRUE的cleanState,并且如果集合中不存在成员,则清除现有数据。 如果要在应用程序重新启动时保留分布式状态,请将其设置为FALSE。
可以选择将logSize的大小设置为默认值32,并用于保存状态更改的历史记录。 这个设置的价值应该是两个幂。 32通常是一个很好的默认值,但是如果一个特定的状态机被留下超过一个日志的大小,它就会进入错误状态,并与一个表示它已经失去历史的集成断开连接,以重建完全同步的状态。