我有一个spring状态机(版本3.0.1),每个用户都有自己的实例。对于每个HTTP请求,状态机都由DefaultStateMachineService
从JpaStateMachineRepository
获取。在HTTP请求结束时,再次释放状态机。状态机配置为使用StateMachineRuntimePersister
在状态机的一个特殊状态下,有一个由计时器触发的转换:
.withExternal()
.source( "S1" )
.target( "S2" )
.timerOnce( 60000 )
我希望只有当状态机仍处于状态S1
时才执行此定时器一分钟后(另一个云实例处理此状态机实例的后续步骤可能会在此期间改变状态,从而使计时器失效)。
- 我试图在不停止状态机(
stateMachineService.releaseStateMachine( machineId, false );
)的情况下释放状态机。那么定时器总是触发,因为它没有从数据库中刷新状态机,导致状态不一致。 我试图释放状态机已停止。然后计时器被杀死,将不再触发。
一个解可以将触发器从timerOnce
切换到event
,并使用单独的机制(例如Quartz调度器)。)从数据库中读取状态机,检查状态,然后显式地触发事件。但是这会使spring状态机的定时器特性在云环境中毫无用处,所以我想应该有一个更好的解决方案。
这里最好的解决方案是什么?
您提到的问题可以使用分布式状态来解决。
所以,Spring statemmachine使用ZooKeeper来保持应用实例中机器的状态一致。在你的例子中,ZooKeeper会让你的状态机知道它在另一个应用实例上的状态是否发生了变化,并根据计时器做出相应的行为。
值得一提的是,根据docs:
,该功能目前还不成熟。分布式状态功能仍然是一个预览特性,在这个特定的版本中尚未被认为是稳定的。我们希望这个功能在第一次正式发布时成熟。
你可以在分布式状态机技术论文
中找到这个概念的一些技术细节。就我个人而言,我会坚持使用您描述的解决方案(使用调度程序触发事件火灾),因为它可以更好地控制进程。