java - Akka 有限状态机实例

标签 java scala akka state-machine

我正在尝试将 Akka 的有限状态机框架用于我的用例。我正在开发一个处理通过各种状态的请求的系统。

这里的请求是需要和它依赖的应用一起部署的应用名称:

Request for application A -> A is in a QUEUED state
Discover A's dependency B -> B is in a QUEUED state
B is being processed -> B is in a PROCESSING STATE
A is being processed -> A is in a PROCESSING STATE
B is processed -> B is in a DONE state
A is processed -> A is in a DONE state

为此,我在发现时初始化一个有限状态机。所以A的 FSM 在请求进来时创建,B的 FSM 在 B 时初始化是从其中一名 Actor 身上发现的。

我是否初始化并将 FSM 实例传递给所有参与者,同时 tell关于正在对数据执行的操作的 FSM,以便状态机进入正确的状态?

这是状态机的相关部分:
when(QUEUED, matchEvent(requestAccepted.class, MyApp.class,
    (requestAccepted, service) -> 
    goTo(PROCESSING).replying(PROCESSING)));

when(PROCESSING, matchEvent(completed.class, MyApp.class,
    (completed, service) -> goTo(DONE).replying(DONE)));

// During transitions, save states in the database.
onTransition(matchState(PROCESSING, DONE, () -> {
  nextStateData().setServiceStatus(DONE);
  databaseWriter.tell(nextStateData(), getSelf());

这是处理请求的参与者之一的示例:
ProcessingActor extends AbstractActor {

    @Override
      public void onReceive(Object message) throws Throwable {
        if (message instanceof processApplication) {
         // process the app
         // Initialize FSM for the Application
         FSM myFSM = Props.create(MYFSM.class);
         myFSM.tell( new completed(processApplication.app)
    }

这是初始化状态机并使用它的正确方法吗?或者初始化应该发生在 ProcessingActor 的构造函数中?但在那种情况下,每个应用程序(数据)不会有一个状态机。

最佳答案

TL; 博士;虽然 OP 中状态和转换的描述相当模糊,但可以解决所选实现的状态、其影响和替代方案。
手头的实现可以算作“每个请求的参与者”方法,而不是更频繁地找到的方法,状态机参与者缓冲和处理多个请求。下面将进一步介绍。
在目前的形式中,给定的实现是我所知道的每个请求的唯一 AbstractFSM,实际上还有另一个 FSM 下游,然后不能再称为“每个请求”,并且可能可以避免。它看起来大致是这样的:
actor per request FSM
“每个请求的 Actor ”最初似乎出现在 this discussion 中。 ,这提高了 this blog稍后甚至偶尔声称a pattern的称号.部分原因似乎是复制了 Spray framework 的功能之一。 ,有点像 Akka http 的前身。
另一个关于 SO 的讨论来到了 inconclusive result关于每个请求是否更喜欢单个 Actor 的问题,并提出 routing作为第三种选择,因为路由器还充当负载平衡器,触及 back-pressure话题。
该方法更频繁地与 AbstractFSM 结合使用。然而,它的品种是一个单一的 FSM Actor ,它缓冲
使用 whenUnhandled 的传入消息默认情况下累积它们的方法,无论当前状态如何(例如 Akka in Action,章节 "Finite State Machines and Agents" 或 Lightbend buncher example)。我无法用引用来支持声明,但看起来 AbstractFSM 更像是对处理多个请求的参与者的状态进行建模,而不是对经过多个阶段的请求的状态进行建模。
与 OP 相关的方法意味着,ProcessingActor本身可以扩展 AbstractFSM .

public class ProcessingActor extends AbstractFSM<sample.so.State, RequestQueue> {
{
    startWith(Idle, new RequestQueue());

    when(Idle, /* matchEvent(EventType, DataType, Action) */
            matchEvent(
                    Request.class,
                    RequestQueue.class,
                    (request, queue) -> goTo(Processing).using(queue.push(request)));
    /* more state-matchers */

    whenUnhandled(
            matchEvent(
                    Request.class,
                    RequestQueue.class,
                    (request, qeue) -> stay().using(qeue.push(request)));

    initialize();
}
到达“请求”部分的类似内容,其中数据库写入不再由状态表示,而不是状态进入和退出操作。注意所有 whenUnhandled分支没有出现在图中,因为它与状态更改无关。
single actor FSM
无需过多地权衡(模糊)对所选实现的要求,AbstractFSM将每个请求的状态序列记录到数据库中似乎是一种相当笨拙的机器。 Akka 2.4 版本的文档介绍了状态机 without使用 AbstractFsm 并讨论区分第一个事件然后状态或相反的可能性。在 AbstractFSM -DSL 你必须在事件(和数据)之前辨别状态。甚至可以有理由放弃 akka FSM altogether .
构建 FSM 的更轻量级方法使用 become/unbecome ,一个不错的演示文稿是 here , 一个 AbstractFSM可以找到与成为/不成为的讨论 here .在视觉上更接近业务规则是前者的主要论据。
进入判断 AbstractFSM 用于任务的更滑的地形。我想,有些事情可以说,考虑到要求的阅读大致可以。
状态形成一个线性链,所以两个“AbstractFSM-per-request”可以被其他的 per-request 结构替换:
  • 单个参与者链,每个参与者代表一个状态

  • chain of actors
  • 单个actor,向自身发送事件,上面显示的每个步骤一种事件类型,在每个点向数据库编写器发送消息。也许枚举也足够了。

  • 考虑到这一点,这些版本的吸引力可能会增加:由于给定的实现对每个请求使用(至少)一个 FSM,问题出现了,如何转换 QUEUED->PROCESSING出现(或 discovery processing -> discovery done),以及什么 QUEUED涉及到一个技术层面。项目永远不会在队列中,总是在一个独占角色中(另一方面,在 single-FSM 方法中,实际上使用队列的方法中 QUEUED 状态会更明显,但随后 状态不适用于角色,但对于 Actor 处理的项目 )。不明显,其中external event应该导致这种转变。 Akka FSM 适用于描述确定性 FSM (另请参阅 this ,出于相反的原因给出相同的论点),但如果此转换不是由外部事件触发,则 FSM 必须变为 nondeterministic并触发自己的 epsilon-transitions ~ 不是由任何输入引起的转换。一个相当复杂的结构,可能是这样实现的:
    onTransition(
        matchState(Initial, Queued, () -> {                    
            getSelf().tell(new Epsilon(), getSelf());
        }));
    

    关于java - Akka 有限状态机实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50681526/

    相关文章:

    java - 仅更改鼠标悬停时字母的颜色

    java - 什么是默认的 Akka 调度程序配置值?

    java - 来自另一个类的 JButton Action 监听器

    java - 如何获取在类中声明为映射的常量

    scala - 将 Spark DataSet 行值映射到新的哈希列

    scala - 在哪里放置定期执行的更新参与者内部状态的计算?

    algorithm - 为Akka Actor 池排序了共享邮箱或总线?

    scala - 是否可以在 Akka 中编写 FSM?

    java.lang.NumberFormatException : for input string {Date}. Spring MVC 我无法识别错误

    scala - 在 Play 中使用 "implicit request"是什么意思?