附录

附录 A:支持内容

本附录提供了有关类和 材料。spring-doc.cn

本文档中使用的类

以下清单显示了本参考指南中使用的类:spring-doc.cn

public enum States {
    SI,S1,S2,S3,S4,SF
}
public enum States2 {
	S1,S2,S3,S4,S5,SF,
	S2I,S21,S22,S2F,
	S3I,S31,S32,S3F
}
public enum States3 {
    S1,S2,SH,
    S2I,S21,S22,S2F
}
public enum Events {
    E1,E2,E3,E4,EF
}

附录 B:状态机概念

本附录提供有关 state machines 的一般信息。spring-doc.cn

快速示例

假设我们有名为 and 的状态和名为 and 的事件,您可以定义状态机的逻辑,如下图所示:STATE1STATE2EVENT1EVENT2spring-doc.cn

状态图0

以下清单定义了上图中的状态机:spring-doc.cn

public enum States {
	STATE1, STATE2
}

public enum Events {
	EVENT1, EVENT2
}
@Configuration
@EnableStateMachine
public class Config1 extends EnumStateMachineConfigurerAdapter<States, Events> {

	@Override
	public void configure(StateMachineStateConfigurer<States, Events> states)
			throws Exception {
		states
			.withStates()
				.initial(States.STATE1)
				.states(EnumSet.allOf(States.class));
	}

	@Override
	public void configure(StateMachineTransitionConfigurer<States, Events> transitions)
			throws Exception {
		transitions
			.withExternal()
				.source(States.STATE1).target(States.STATE2)
				.event(Events.EVENT1)
				.and()
			.withExternal()
				.source(States.STATE2).target(States.STATE1)
				.event(Events.EVENT2);
	}
}
@WithStateMachine
public class MyBean {

	@OnTransition(target = "STATE1")
	void toState1() {
	}

	@OnTransition(target = "STATE2")
	void toState2() {
	}
}
public class MyApp {

	@Autowired
	StateMachine<States, Events> stateMachine;

	void doSignals() {
		stateMachine
			.sendEvent(Mono.just(MessageBuilder
				.withPayload(Events.EVENT1).build()))
			.subscribe();
		stateMachine
			.sendEvent(Mono.just(MessageBuilder
				.withPayload(Events.EVENT2).build()))
			.subscribe();
	}
}

词汇表

状态机

驱动状态集合的主要实体,以及区域 transitions 和 events 的 Transitions 和 Events。spring-doc.cn

状态 (state) 模拟了某些不变条件 holds。状态是状态机的主要实体,状态会发生变化 由事件驱动。spring-doc.cn

扩展状态

扩展状态是保存在状态中的一组特殊变量 machine 来减少所需状态的数量。spring-doc.cn

过渡

过渡是源状态和目标之间的关系 州。它可能是复合转换的一部分,该转换采用状态 machine 从一个 state 配置切换到另一个 state 配置,表示完整的 状态机对 特定类型。spring-doc.cn

事件

一个实体,它被发送到状态机,然后驱动各种 状态更改。spring-doc.cn

初始状态

状态机启动的特殊状态。初始状态为 始终绑定到特定的状态机或区域。状态 具有多个区域的计算机可能具有多个初始状态。spring-doc.cn

结束状态

(也称为最终状态。一种特殊的状态表示 表示封闭区域已完成。如果封闭区域为 直接包含在状态机和 state machine 也都已完成,则整个 state 机器完成。spring-doc.cn

历史记录状态

一个伪状态,让状态机记住它的最后一个 active 状态。存在两种类型的历史状态:浅层(即 仅记住顶级状态)和 deep(记住 子机器)。spring-doc.cn

选择状态

一个伪状态,允许根据 (例如) 事件标头或扩展状态变量。spring-doc.cn

交汇点状态

一个伪状态,它与 choice state 相对相似,但允许 多个传入过渡,而 choice 只允许一个传入 过渡。spring-doc.cn

分叉状态

一种伪状态,用于受控地进入区域。spring-doc.cn

加入状态

一种伪状态,它提供对区域的受控退出。spring-doc.cn

入场点

允许受控进入 submachine的伪状态。spring-doc.cn

退出点

允许从子机中受控退出的伪状态。spring-doc.cn

地区

区域是复合状态或状态的正交部分 机器。它包含状态和转换。spring-doc.cn

警卫

根据 扩展状态变量和事件参数。守卫条件影响 通过启用 actions 或 transitions 实现状态机的行为 仅当他们评估时禁用他们 自。TRUEFALSEspring-doc.cn

行动

操作是在触发 过渡。spring-doc.cn

状态机速成课程

本附录提供了状态机的通用速成课程 概念。spring-doc.cn

状态

状态是状态机所在的模型。它总是 更容易将 state 描述为真实世界的示例,而不是尝试使用 抽象概念在通用文档中。为此,请考虑 一个简单的键盘例子 — 我们大多数人每天都会使用一个。 如果您有一个完整的键盘,左侧有普通键,并且 数字键盘,您可能已经注意到了 数字键盘可能处于两种不同的状态,具体取决于 numlock 已激活。如果它未激活,请按数字键盘键 使用箭头等进行导航。如果数字键盘处于活动状态,请按 这些键会导致键入数字。本质上,键盘的数字键盘部分 可以处于两种不同的状态。spring-doc.cn

将状态概念与编程相关联,这意味着不是使用 标志、嵌套的 if/else/break 子句或其他不切实际(有时是曲折的)逻辑,您可以 依赖状态、状态变量或与 状态机。spring-doc.cn

伪状态

伪状态是一种特殊类型的状态,通常会引入更多 更高级别的 logic 添加到状态机中,方法是给状态一个 特殊含义(如 initial state)。然后,状态机可以在内部 通过执行 UML 状态中可用的各种操作来对这些状态做出反应 机器概念。spring-doc.cn

每个状态始终需要 Initial pseudostate state state machine 的 Machine,无论您拥有简单的单级状态机还是更多的 由子机或区域组成的复杂状态机。初始 state 定义状态机启动时应去哪里。 没有它,状态机就会出现错误。spring-doc.cn

结束

Terminate 伪状态(也称为 “end state”) 表示 特定状态机已达到其最终状态。有效 这意味着状态机不再处理任何事件,并且 不转机到任何其他州。但是,如果 submachines 是 regions,则状态机可以从其 terminal 状态重新启动。spring-doc.cn

选择

您可以使用 Choice 伪状态选择 从此状态过渡。动态条件由守卫评估 ,以便选择一个分支。通常为 使用简单的 if/elseif/else 结构来确保 branch 处于选中状态。否则,状态机可能会陷入死锁。 并且配置格式不正确。spring-doc.cn

Junction 伪状态在功能上类似于 choice,因为两者都是 使用 if/elseif/else 结构实现。唯一真正的区别是 该 Junction 允许多个传入转换,而 CHOICE 只允许一个。因此,差异在很大程度上是学术性的,但确实有一些 差异(例如,何时设计状态机)与实际 UI 建模一起使用 框架。spring-doc.cn

历史

您可以使用 History 伪状态来记住最后一个活动状态 配置。退出状态机后,您可以使用历史状态 以恢复以前已知的配置。有两种类型 的可用历史记录状态:(它只记住 状态机本身)和 (它也记住嵌套状态)。SHALLOWDEEPspring-doc.cn

历史状态可以通过侦听状态在外部实现 machine 事件,但这很快就会变得非常困难的 logic, 特别是当状态机包含复杂的嵌套结构时。 让状态机本身处理历史状态的记录 让事情变得简单得多。用户只需创建一个 transition 转换为 history 状态,状态机会处理所需的 logic 返回到其上一个已知的记录状态。spring-doc.cn

如果 Transition 在历史状态上终止,当状态 之前未输入(换句话说,不存在以前的历史记录)或已达到其 end 状态,则 transition 可以强制状态机进入特定的子状态,方法是 使用默认的 History 机制。此过渡源于 并终止于特定顶点(默认 history state) 的 STATE 的 STATE 中。此过渡是 仅当其执行导致历史状态并且该状态以前从未过时时才采取 积极。否则,将执行该区域的正常历史记录条目。 如果未定义默认历史记录过渡,则 执行 Region。spring-doc.cn

您可以使用 Fork 伪状态对一个或多个区域进行显式输入。 下图显示了 fork 的工作原理:spring-doc.cn

状态图7

目标状态可以是托管区域的父状态,它只是 表示通过输入区域的初始状态来激活区域。你 还可以将目标直接添加到区域中的任何状态,这 允许更受控地进入状态。spring-doc.cn

加入

Join 伪状态将多个转换合并在一起,这些转换 源自不同的区域。一般用来等待 和 block 以进入其 Join 目标状态。 下图显示了联接的工作原理:spring-doc.cn

状态图8

源状态可以是托管区域的父状态,这意味着 join states 是参与区域的终端状态。 您还可以将源状态定义为 region,它允许受控地退出 Region。spring-doc.cn

入场点

Entry Point 伪状态表示状态的入口点 machine 或提供内部封装的复合状态 状态或状态机。在状态机的每个区域中,或 复合状态,则最多只有一个 从入口点过渡到该区域内的顶点。spring-doc.cn

退出点

Exit Point 伪状态是状态机的退出点,或者 提供 state 内部封装的复合 state 或状态机。在任何 区域(或 submachine 状态)表示退出此复合状态或 submachine state (执行其关联的退出行为)。spring-doc.cn

守卫条件

保护条件是基于扩展状态变量和事件参数计算结果为 或 的表达式。警卫 与 action 和 transitions 一起使用,以动态选择 应运行特定的操作或过渡。警卫的各方面, 事件参数和扩展状态变量的存在来生成状态 机器设计要简单得多。TRUEFALSEspring-doc.cn

事件

Event 是驱动状态机最常用的触发器行为。 还有其他方法可以在状态机中触发行为 (例如计时器),但事件才是真正允许用户 与状态机交互。事件也称为 “信号”。 它们基本上表示可能改变状态机状态的东西。spring-doc.cn

转换

过渡是源状态和目标之间的关系 州。从一种状态切换到另一种状态是导致的状态转换 通过触发器。spring-doc.cn

内部过渡

当需要运行操作时,使用 Internal transition,而无需 导致状态转换。在内部转换中,源状态和目标 state 始终相同,它与 缺少 state entry 和 exit 操作。spring-doc.cn

外部过渡与局部过渡

在大多数情况下,外部和局部过渡在功能上是 等效的,除非在 super 之间发生转换 和子州。本地过渡不会导致 exit 和 entry 到 Source state(源状态):如果目标状态是源状态的子状态。 相反,本地过渡不会导致 Target 的退出和进入 state 如果目标是源状态的超状态。 下图显示了本地转换和外部转换之间的区别 使用非常简单的 super 和 sub 状态:spring-doc.cn

状态图4

触发器

触发器开始过渡。触发器可以由事件或计时器驱动。spring-doc.cn

行动

Action 确实会粘附状态机状态更改 添加到用户自己的代码中。状态机可以在各种 更改和状态机中的步骤(例如进入或退出状态) 或执行状态转换。spring-doc.cn

操作通常可以访问状态上下文,该上下文提供运行 编写 CHOICE 代码以各种方式与状态机交互。 状态上下文公开了整个状态机,以便用户可以 访问扩展状态变量、事件标头(如果转换基于 在事件上)或实际过渡(可以看到更多 详细说明此 state 更改的来源和去向)。spring-doc.cn

分层状态机

分层状态机的概念用于简化状态 当特定状态必须共存时进行设计。spring-doc.cn

分层状态实际上是 UML 状态机的一项创新 传统的状态机,如 Mealy 或 Moore 机。 Hierarchical states 允许您定义某种级别的抽象(parallel 到 Java 开发人员如何使用 abstract 定义类结构 类)。例如,对于嵌套状态机,您可以 在多个状态级别上定义过渡(可能使用 不同的条件)。状态机总是尝试查看当前 state 能够处理事件,并且 transition guard 条件。如果这些条件的计算结果未为 ,则状态 机器只能看到 Super State 可以处理什么。TRUEspring-doc.cn

地区

通常查看区域(也称为正交区域) 作为应用于状态的异 OR (XOR) 运算。区域中的概念 状态机的术语通常有点难以理解, 但是通过一个简单的例子,事情会变得简单一些。spring-doc.cn

我们中的一些人有一个全尺寸键盘,主键在左侧,数字 键。您可能已经注意到,双方真的 都有自己的状态,如果您按下 “numlock” 键(它 仅改变数字键盘本身的行为)。如果您没有全尺寸 键盘,您可以购买外部 USB 数字键盘。 假设键盘的左侧和右侧都可以存在,而没有 其他,它们必须具有完全不同的状态,这意味着它们是 在不同的状态机上操作。在状态机术语中,一个 键盘是一个区域,数字键盘是另一个区域。spring-doc.cn

处理两个不同的 状态机作为完全独立的实体,因为它们 仍然以某种方式一起工作。这种独立性允许正交区域 在单个状态中以多个同步状态组合在一起 在状态机中。spring-doc.cn

附录 C:分布式状态机技术论文

本附录提供了有关 将 Zookeeper 实例与 Spring Statemachine 一起使用。spring-doc.cn

抽象

在单个状态机之上引入“分布式状态” 在单个 JVM 上运行的实例是一个困难且复杂的主题。 “分布式状态机”的概念引入了一些相对复杂的 由于运行到完成 模型,更一般地说,由于其单线程执行模型 尽管正交区域可以并行运行。另一种天然 问题是状态机转换执行是由触发器驱动的, 它们要么是基于 or 的。eventtimerspring-doc.cn

Spring State Machine 尝试解决 spanning 问题 通过支持分布式 状态机。在这里,我们向您展示了您可以使用 generic 跨多个 JVM 和 Spring 的“状态机”概念 应用程序上下文。spring-doc.cn

我们发现,如果仔细选择抽象 支持分布式状态存储库可以保证准备就绪,这是 可以创建一个可以共享的 distributed 状态。Distributed State MachineCPspring-doc.cn

我们的结果表明,如果支持 repository 是 “CP” (稍后讨论)。 我们预计我们的分布式状态机可以提供 需要使用共享分布式的应用程序的基础 国家。该模型旨在为云应用程序提供良好的方法 拥有更简单的相互通信方式,而无需 显式构建这些分布式状态概念。spring-doc.cn

介绍

Spring State Machine 不强制使用单线程执行 model 执行,因为一旦使用了多个 Region,Region 就可以在 parallel (如果应用了必要的配置)。这是一个重要的 topic 的 Topic,因为一旦用户想要拥有并行状态机 执行,它使独立区域的状态更改更快。spring-doc.cn

当状态更改不再由本地 JVM 或 本地状态机实例,需要控制转换逻辑 外部的任意持久存储中。此存储需要 有办法在分发时通知参与的状态机 state 已更改。spring-doc.cn

CAP 定理指出 分布式计算机系统不可能同时 提供以下所有三个保证:一致性、 可用性和分区容错性。spring-doc.cn

这意味着, 无论选择什么作为后备持久化存储,都是可取的 改为 “CP”。在这种情况下,“CP”的意思是“一致性”和“分区” 宽容”。自然,分布式 Spring Statemachine 并不关心 关于其 “CAP” 级别,但实际上为 “一致性” 和 “分区容错性”比“可用性”更重要。这是 (例如)Zookeeper 使用“CP”存储的确切原因。spring-doc.cn

本文中介绍的所有测试都是通过运行自定义 Jepsen 在以下环境中进行测试:spring-doc.cn

  • 具有节点 n1、n2、n3、n4 和 n5 的集群。spring-doc.cn

  • 每个节点都有一个实例,该实例构造一个 ensemble 所有其他节点。Zookeeperspring-doc.cn

  • 每个节点都安装了一个 Web 示例, 以连接到本地节点。Zookeeperspring-doc.cn

  • 每个状态机实例仅与本地实例通信。将计算机连接到多个实例时 是可能的,这里不使用。Zookeeperspring-doc.cn

  • 所有状态机实例在启动时,都会使用 Zookeeper ensemble 创建一个。StateMachineEnsemblespring-doc.cn

  • 每个示例都包含一个自定义的 rest API,Jepsen 使用该 API 发送 事件并检查特定状态机状态。spring-doc.cn

Jepsen 的所有测试均可从 Jepsen 获得 测试。Spring Distributed Statemachinespring-doc.cn

通用概念

a 的一个设计决策是不让每个 单个状态机实例,请注意它是 “分布式集成”。由于 a 的主要功能和特性可以通过其界面访问,因此 将此实例包装在 中,该实例 拦截所有状态机通信并与 ensemble 来编排分布式状态更改。Distributed State MachineStateMachineDistributedStateMachinespring-doc.cn

另一个重要的概念是能够足够持久 来自状态机的信息,用于重置状态机状态 从任意状态转换为新的反序列化状态。这很自然 当新的状态机实例加入 ensemble 时需要 并且需要将自己的内部 state 与分布式 州。连同使用分布式 state 和 state 的概念 persist 时,可以创建分布式状态机。 目前,唯一的后备仓库是 使用 Zookeeper 实现。Distributed State Machinespring-doc.cn

使用分布式状态中所述,分布式状态由 将 a 的实例包装在 .具体实现方式为 与 Zookeeper 集成。StateMachineDistributedStateMachineStateMachineEnsembleZookeeperStateMachineEnsemblespring-doc.cn

的作用ZookeeperStateMachinePersist

我们想要一个通用接口 () 可以持久保存到任意存储中,并为 实现此接口。StateMachinePersistStateMachineContextZookeeperStateMachinePersistZookeeperspring-doc.cn

的作用ZookeeperStateMachineEnsemble

虽然分布式状态机使用一组序列化的 contexts 来更新自己的 state,使用 zookeeper,我们有一个 关于如何监听这些上下文变化的概念问题。我们 可以将上下文序列化为 zookeeper,并最终 在数据被修改时监听。但是,没有 保证您每次数据更改都会收到通知, 因为 A 的注册一旦触发就会被禁用 并且用户需要重新注册该 .在这短短的时间里, 可以更改数据,从而导致丢失事件。是的 实际上很容易通过更改数据来错过这些事件 多个线程。znodeznodeZookeeperwatcherznodewatcherznodespring-doc.cn

为了解决这个问题,我们保留了单独的上下文更改 in multiple 中,我们使用一个简单的整数计数器来标记 这是当前活动的。这样做可以让我们重播错过的 事件。我们不想创建越来越多的 znodes,然后再创建 删除旧的。相反,我们使用循环的简单概念 znode 集。这允许我们使用一组预定义的 znode,其中 当前节点可以用一个简单的整数计数器来确定。我们已经有 此计数器通过跟踪主数据版本 (在 中是一个整数) 。znodesznodeznodeZookeeperspring-doc.cn

循环缓冲区的大小必须为 2 的幂,以避免 当整数溢出时出现问题。因此,我们不需要 处理任何特定情况。spring-doc.cn

分布式容差

显示针对状态的各种分布式操作 机器在现实生活中工作时,我们使用一组 Jepsen 测试 模拟在实际分布式 簇。这些包括网络级别的“大脑分裂”、并行 具有多个“分布式状态机”的事件,以及 “扩展状态变量”。Jepsen 测试基于一个示例 Web,该示例实例在 多个主机以及每个节点上的 Zookeeper 实例 运行状态机的位置。本质上,每个状态机样本 连接到本地 Zookeeper 实例,这允许我们使用 Jepsen,用于模拟网络条件。spring-doc.cn

本章后面显示的绘图包含的状态和事件 直接映射到状态图,您可以在 Web 中找到该图。spring-doc.cn

孤立的事件

将隔离的单个事件发送到 ensemble 是最简单的测试场景,它演示了 一个状态机中的状态更改会正确地传播到其他状态机 集成中的状态机。spring-doc.cn

在此测试中,我们演示了一台计算机中的状态更改 最终导致其他计算机发生一致的状态更改。 下图显示了测试状态机的事件和状态更改:spring-doc.cn

SM Tech 隔离活动

在上图中:spring-doc.cn

  • 所有计算机都报告 状态 。S21spring-doc.cn

  • 事件被发送到节点,并且所有节点都报告状态更改 从 到 。In1S21S22spring-doc.cn

  • 事件被发送到节点,并且所有节点都报告状态更改 从 到 。Cn2S22S211spring-doc.cn

  • 事件被发送到节点,并且所有节点都报告状态更改 从 到 。In5S211S212spring-doc.cn

  • 事件被发送到节点,并且所有节点都报告状态更改 从 到 。Kn3S212S21spring-doc.cn

  • 我们循环事件 、 、 ,再一次,通过随机节点。ICIKspring-doc.cn

平行活动

多个分布式状态机的一个逻辑问题是,如果 同一事件以完全相同的方式发送到多个状态机 time 时,这些事件中只有一个会导致分布式状态 转换。这在某种程度上是意料之中的场景,因为第一个状态 machine(对于此事件)能够更改分布式状态 控制分布式转换逻辑。实际上,所有其他 接收到此相同事件的计算机会以静默方式丢弃该事件, 因为分布式状态不再处于特定的 事件。spring-doc.cn

在下图所示的测试中,我们演示了由 parallel 事件最终会导致 所有计算机中的一致状态更改:spring-doc.cn

SM Tech 平行活动

在上图中,我们使用了与上一个示例相同的事件流 (隔离事件),不同之处在于事件始终是 发送到所有节点。spring-doc.cn

并发扩展状态变量更改

扩展状态机变量不保证在 任何给定时间,但是,在分布式状态更改后,所有状态机 在 ensemble 中应该有一个 synchronized extended 状态。spring-doc.cn

在此测试中,我们演示了扩展状态的更改 一个分布式状态机中的变量最终会变成 在所有分布式状态机中保持一致。 下图显示了此测试:spring-doc.cn

SM Tech 使用变量

在上图中:spring-doc.cn

  • 将事件发送到事件变量值为 的节点。然后,所有节点都报告具有一个名为 的变量。Jn5testVariablev1testVariablev1spring-doc.cn

  • Event 从 variable 到 重复执行相同的检查。Jv2v8spring-doc.cn

分区容错

我们需要始终假设,迟早会在集群中 变坏,无论是 Zookeeper 实例的崩溃,还是 state 机器崩溃,或网络问题,例如“大脑分裂”。(脑分裂是一个 现有集群成员被隔离,因此只有 部分主机能够看到彼此)。通常的情况是 brain split 创建 ensemble 的集合,使得少数主持人无法参与集合 直到网络状态已修复。spring-doc.cn

在下面的测试中,我们证明了各种类型的大脑分裂成 一个 ensemble 最终会导致所有 分布式状态机。spring-doc.cn

有两种情况在 网络,其中 where 和 instances 所在的 拆分为两半(假设每个都连接到 local 实例):ZookeeperStatemachineStatemachineZookeeperspring-doc.cn

  • 如果当前的 zookeeper leader 保持多数,则所有 Client 端 连接到大多数保持正常运行。spring-doc.cn

  • 如果当前的 zookeeper 领导者是少数,则所有客户端 断开与它的连接并尝试重新连接到上一个 少数成员已成功重新加入现有的多数成员 整体。spring-doc.cn

在我们当前的 Jepsen 测试中,我们无法分离 Zookeeper 裂脑 领先者处于多数或少数状态之间的情况,因此我们需要 多次运行测试以完成此情况。
在下图中,我们将状态机错误状态映射到 an,以指示状态机处于错误状态,而不是 正常状态。在解释图表状态时,请记住这一点。error

在第一个测试中,我们表明,当现有的 Zookeeper 领导者 保持大多数,五分之三的机器继续保持原样。 下图显示了此测试:spring-doc.cn

SM Tech 隔断 Half 1

在上图中:spring-doc.cn

  • 第一个事件 被发送到所有计算机,导致状态更改为 。CS211spring-doc.cn

  • Jepsen 复仇女神会导致大脑分裂,从而导致分裂 的 和 。节点是少数,并且 节点构建一个新的健康多数。节点 大多数节点保持正常运行,但少数节点 进入 ERROR 状态。n1/n2/n5n3/n4n3/n4n1/n2/n5spring-doc.cn

  • Jepsen 修复网络,一段时间后,节点加入 返回到 ensemble 并同步其 distributed 状态。n3/n4spring-doc.cn

  • 最后,将 event 发送到所有状态机,以确保 ensemble 工作正常。此状态更改会导致返回状态 。K1S21spring-doc.cn

在第二个测试中,我们表明,当现有的 zookeeper leader 是 保持少数,所有机器都会出错。 下图显示了第二个测试:spring-doc.cn

SM Tech 隔断 2

在上图中:spring-doc.cn

  • 第一个事件 将发送到所有计算机,从而导致状态更改为 。CS211spring-doc.cn

  • Jepsen 复仇女神会导致大脑分裂,从而导致分裂 这样,现有的领导人就保持在少数派和所有 实例与 Ensemble 断开连接。Zookeeperspring-doc.cn

  • Jepsen 修复网络,一段时间后,所有节点都加入 返回到 ensemble 并同步其 distributed 状态。spring-doc.cn

  • 最后,将 event 发送到所有状态机,以确保 ensemble 正常工作。此状态更改会导致返回状态 。K1S21spring-doc.cn

碰撞和合并容差

在这个测试中,我们演示了杀死一个现有的状态机 然后将新实例连接回 ensemble 中,将 分布式状态 Healthy 和新加入的状态机同步 他们的状态正确。 下图显示了崩溃和连接容差测试:spring-doc.cn

SM Tech 停止启动
在此测试中,不会检查第一个 和最后一个 之间的状态。 因此,该图在两者之间显示一条平坦线。检查状态 正是 和 之间状态变化发生的位置。XXS21S211

在上图中:spring-doc.cn

  • 所有状态机都从初始状态 () 转换为 state 的 intent 中,这样我们就可以在 join 期间测试正确的 state synchronize。S21S211spring-doc.cn

  • X标记特定节点何时崩溃并启动。spring-doc.cn

  • 同时,我们从所有机器请求状态并绘制结果。spring-doc.cn

  • 最后,我们做一个简单的转换,从 from 到 make 确保所有状态机仍然正常运行。S21S211spring-doc.cn

开发人员文档

本附录为开发人员提供了通用信息,他们可能会 想要贡献或其他想要了解 state 的人 机器工作或理解其内部概念。spring-doc.cn

StateMachine 配置模型

StateMachineModel和其他相关的 SPI 类是抽象的 在各种 configuration 和 factory 类之间。这也允许 其他人可以更轻松地集成以构建状态机。spring-doc.cn

如下面的清单所示,您可以通过构建模型来实例化状态机 使用配置数据类,然后要求工厂构建 状态机:spring-doc.cn

// setup configuration data
ConfigurationData<String, String> configurationData = new ConfigurationData<>();

// setup states data
Collection<StateData<String, String>> stateData = new ArrayList<>();
stateData.add(new StateData<String, String>("S1", true));
stateData.add(new StateData<String, String>("S2"));
StatesData<String, String> statesData = new StatesData<>(stateData);

// setup transitions data
Collection<TransitionData<String, String>> transitionData = new ArrayList<>();
transitionData.add(new TransitionData<String, String>("S1", "S2", "E1"));
TransitionsData<String, String> transitionsData = new TransitionsData<>(transitionData);

// setup model
StateMachineModel<String, String> stateMachineModel = new DefaultStateMachineModel<>(configurationData, statesData,
		transitionsData);

// instantiate machine via factory
ObjectStateMachineFactory<String, String> factory = new ObjectStateMachineFactory<>(stateMachineModel);
StateMachine<String, String> stateMachine = factory.getStateMachine();