作为演员粒度

Akka actor granularity

我第一次尝试思考 Akka/actors,对每个 Actor 职责的粒度有点困惑。

在我的应用程序中有 Widget 可以是 registered/unregistered 和 WidgetRegistrar。向 Registrar 注册自身,并将 Widget 传递给 registerWidget 方法:

interface WidgetRegistrar {
    public void register(Widget w);
}

Widget 尝试注册时,会发生验证过程。如果此过程通过,则 Widget 会呈现一个 URL,必须不断(每秒一次)轮询和检查(使用 HTTP GET)以确保 URL 仍然健康。

我的问题是:这个工作量应该如何分配给演员?

我马上就能想到几种不同的策略:

或不同的策略:

或不同的策略:

...变体列表不断增加。

所以我问:Akka actor 的粒度是多少,我怎么知道什么时候应该将功能分解为另一个 actor 并以某种方式连接这两个 actor?

Akka 意识形态是 'let it crash',因此最好将具有潜在危险的功能隔离到一个单独的参与者中。

我会怎么做 - 演员层次结构示例:

/master
    /validator
        /authentication
        /capability
    /registrar
        /widget1
        /widget2
        /widget3

假设您可能希望在您的注册商中拥有除 register/unregister 之外的针对单个小部件的更多功能,最好在特定根目录下分隔小部件 - 例如,如果您的小部件具有功能就像 'update',你在 /registrar/widget1 中调用这个逻辑,如果更新失败,widget1 actor 就会死掉。根据您的需要,您可能需要重新注册小部件,或设置主管层次结构以自动重启小部件参与者。

使用 validators/verifiers 和其他逻辑 - 您可以在验证器上构建管道(顺序处理)或分散-收集(并行),例如:

  • /master 发送消息给/validator AttemptRegister(WidgetInfo)
  • /validator 将此消息发送给它的所有子节点(例如通过 ask 模式),并期待 Accept(WidgetInfo)Reject(WidgetInfo) - 如果没有拒绝 - 它会发送RegisterWidget/registrar 并且注册商将产生一个新的 /registrar/widget2.

当然,这完全取决于具体的用例——例如:

  • 验证会崩溃或阻塞吗?那么你需要 /validator/capability/doOrDieActor1
  • 您需要顺序 processing/pipeline 吗?你可能想要实现这个序列,比如 ../authentication 将发送 PassFail../authorization,然后将它发送到 capability 等等 - 只有最后的演员会将 ValidationSucceeded 发送到 /validator,后者又将 RegisterWidget 事件发送到 registrar