DefaultStateMachineExecutor 中维护的延迟事件列表在 spring 状态机中丢失
Deferred Event list maintained in DefaultStateMachineExecutor is lost in spring state machine
背景:
在我们典型的状态机工作模型中,我们使用状态机来监控spring-由spring云流微服务完成的批处理。
更准确地说,我们创建流,比如说,命名为 ItemStream ,部署了 source 、 process 、 sink 微服务,用于批量读取、处理和写入记录;分别 。
在执行这些活动时,我们触发 REST 调用,每个调用由流操作之间的一个事件组成。我们在状态机微服务中使用这些 REST 调用,并相应地在机器实例上触发这些事件。在状态机级别,每次处理完成后,我们使用 JPA/Redis State Machine Persister 将状态机上下文持久化到持久存储(database/Redis 缓存)。
当从流中接收到新的 REST 调用时,我们从持久存储中恢复机器上下文,并用它填充一个新的状态机对象;以便准备那个新的机器对象,使其具有以前存在的机器状态。
注意: 这里 'populate the fresh state machine object' 只是意味着我们每次使用机器工厂调用创建新实例,因为我们尚未将机器对象池实现插入和弹出已使用的 StateMachine 对象在需要的时候而不是每次都创建新的实例。
问题:
但是,现在我们面临的问题是,我们已经在 uml 文件中为特定状态(例如状态 PROCESSEDCHUNK)配置了延迟事件(例如 CompleteChunk_1)。
现在,当机器处于 PROCESSEDCHUNK 状态时触发 CompleteChunk_1 事件后,此事件确实被推迟,即正确地停在一边。现在,只要达到在 transition 中映射该事件的特定未来状态(即 WRITECHUNK ),机器就应该自行触发此停放事件。
但是,一旦机器达到该状态,即处于 WRITECHUNK 状态,机器就不会自行触发先前停放在机器延迟列表中的 CompleteChunk_1 事件。
观察结果
**1.**在解决问题后,我注意到状态机的成员 属性 'stateMachineExecutor' 持有在数据结构中维护延迟列表的 DefaultStateMachineExecutor 实例 'ConcurrentLinkedList' 本身。这个执行器每次都在 AbstractStateMachine class 状态机的 onInit() 方法中实例化为新的执行器。因此,我相信每当从工厂创建新实例并且使用先前的持久上下文恢复机器对象时,我们都会丢失停放在该执行程序的 "deferredList" 中的延迟事件。因为 OOB persistence/restoring 不 persist/restore 执行者的状态,因此存在于该执行者上的延迟列表将丢失。
所以在我们的例子中,当机器进入正确的状态,即 WRITECHUNK 时,执行者已经丢失了在过去的事件调用中停放的延迟事件。因此它们现在不能由机器自动触发,因为执行器中现在不存在停放的事件。
**2.**在 spring 文档中给出的简单状态机示例中,我尝试配置延迟事件并且它正常工作并且在达到有效状态后停放事件确实被自动触发。在这些例子中,状态机被启动并且运行从第一个事件到最后一个事件不断。因此,机器的相同实例对象持有相同的 DefaultStateMachineExecutor 实例直到结束工作。
3.Maven依赖库版本如下:
a.spring-状态机核心:2.0.0
b.spring-statemachine-uml : 2.0.0
请求解决方案??
那么,在查看我们保留上下文并在收到的每个 REST 调用上恢复它这一事实时,是否需要任何设计更改或处理 DefaultStateMachineExecutor 的这种情况?或者我想念关于我在排除故障时得出的上述结论的某些内容??
提前致谢。
是的,这需要对机器本身进行一些更改。这是一个有点复杂的问题,一般来说,我们需要坚持不懈地彻底检查其他与事件相关的事情。这些在 gh-550
中进行了跟踪
背景:
在我们典型的状态机工作模型中,我们使用状态机来监控spring-由spring云流微服务完成的批处理。 更准确地说,我们创建流,比如说,命名为 ItemStream ,部署了 source 、 process 、 sink 微服务,用于批量读取、处理和写入记录;分别 。 在执行这些活动时,我们触发 REST 调用,每个调用由流操作之间的一个事件组成。我们在状态机微服务中使用这些 REST 调用,并相应地在机器实例上触发这些事件。在状态机级别,每次处理完成后,我们使用 JPA/Redis State Machine Persister 将状态机上下文持久化到持久存储(database/Redis 缓存)。 当从流中接收到新的 REST 调用时,我们从持久存储中恢复机器上下文,并用它填充一个新的状态机对象;以便准备那个新的机器对象,使其具有以前存在的机器状态。 注意: 这里 'populate the fresh state machine object' 只是意味着我们每次使用机器工厂调用创建新实例,因为我们尚未将机器对象池实现插入和弹出已使用的 StateMachine 对象在需要的时候而不是每次都创建新的实例。
问题:
但是,现在我们面临的问题是,我们已经在 uml 文件中为特定状态(例如状态 PROCESSEDCHUNK)配置了延迟事件(例如 CompleteChunk_1)。 现在,当机器处于 PROCESSEDCHUNK 状态时触发 CompleteChunk_1 事件后,此事件确实被推迟,即正确地停在一边。现在,只要达到在 transition 中映射该事件的特定未来状态(即 WRITECHUNK ),机器就应该自行触发此停放事件。 但是,一旦机器达到该状态,即处于 WRITECHUNK 状态,机器就不会自行触发先前停放在机器延迟列表中的 CompleteChunk_1 事件。
观察结果
**1.**在解决问题后,我注意到状态机的成员 属性 'stateMachineExecutor' 持有在数据结构中维护延迟列表的 DefaultStateMachineExecutor 实例 'ConcurrentLinkedList' 本身。这个执行器每次都在 AbstractStateMachine class 状态机的 onInit() 方法中实例化为新的执行器。因此,我相信每当从工厂创建新实例并且使用先前的持久上下文恢复机器对象时,我们都会丢失停放在该执行程序的 "deferredList" 中的延迟事件。因为 OOB persistence/restoring 不 persist/restore 执行者的状态,因此存在于该执行者上的延迟列表将丢失。 所以在我们的例子中,当机器进入正确的状态,即 WRITECHUNK 时,执行者已经丢失了在过去的事件调用中停放的延迟事件。因此它们现在不能由机器自动触发,因为执行器中现在不存在停放的事件。
**2.**在 spring 文档中给出的简单状态机示例中,我尝试配置延迟事件并且它正常工作并且在达到有效状态后停放事件确实被自动触发。在这些例子中,状态机被启动并且运行从第一个事件到最后一个事件不断。因此,机器的相同实例对象持有相同的 DefaultStateMachineExecutor 实例直到结束工作。
3.Maven依赖库版本如下:
a.spring-状态机核心:2.0.0 b.spring-statemachine-uml : 2.0.0
请求解决方案??
那么,在查看我们保留上下文并在收到的每个 REST 调用上恢复它这一事实时,是否需要任何设计更改或处理 DefaultStateMachineExecutor 的这种情况?或者我想念关于我在排除故障时得出的上述结论的某些内容??
提前致谢。
是的,这需要对机器本身进行一些更改。这是一个有点复杂的问题,一般来说,我们需要坚持不懈地彻底检查其他与事件相关的事情。这些在 gh-550
中进行了跟踪