Akka Stateful Actor 跨节点复制

Akka Stateful Actor Replication Across Nodes

我有一个 Akka 应用程序,我 运行 作为使用 Play Framework 的 Web 应用程序。当我启动这个应用程序时,我创建了一组演员,这些演员有状态。这些参与者响应外部消息并改变状态(我使用 context.become(...) 机制改变状态)。

我现在想要 运行 此 Web 应用程序的多个实例,以便我可以有弹性。但问题是 Web 应用程序公开了前端应用程序连接到的 WebSocket 端点。然后,我每 4 秒通过 WebSocket 端点将 Actor 实例的状态流式传输到前端应用程序。

我这里有几个问题:

  1. 如何 运行 我的 Play Framework Web 应用程序的更多实例,请记住我有状态参与者!我想确保如果其中一个实例宕机,那个实例中的有状态参与者会恢复到宕机前的状态。 Akka 集群分片是可行的方法吗?

  2. 假设我的应用程序中有 10000 个这样的 Stateful actor,我如何利用 Akka Cluster Sharding 使得并非所有这 10000 个 actor 运行 都在同一个节点中?我的意思是如何在节点 1 上创建前 5000 个演员 运行,在节点 2 上创建下一个 5000 运行?现在我对单个实例所做的是,当我启动我的应用程序时,我读取数据库并使用数据为每个数据库行启动一个 actor 实例。

  3. 询问模式如何与集群分片一起使用?我发送到分片区域的任何消息都将被路由到相应的 Actor 实例,但是如何从特定的 actor 请求消息呢?它也会以同样的方式工作吗?我向 Actor 请求消息,我将询问请求发送到分片区域,然后该分片区域将此消息转发给相应的 Actor?这是正确的吗?

有什么建议吗?

设置 akka 集群的方法有两种:

  1. 按照您的建议让所有 Play Framework 实例形成一个集群
  2. 设置一个单独的 akka 集群(如果需要,可以将其称为后端),并使用 Play Framework 实例中的集群客户端连接并与您的集群交互

在上述两种情况下,我会使用集群分片模块来实现您想要实现的目标。

您没有说清楚您的 actor 状态当前是如何持久化的。是否所有状态更改都以某种方式写回数据库?如果你什么都没有,Akka 持久性可能会帮助你。

针对您的问题:

  1. 集群分片将负责将您的 actor 拆分为多个 运行 实例,并在实例关闭或启动时迁移它们。集群分片根本不会处理你的演员的状态。这是一个完全独立的问题,这就是我在上面提到 akka 持久性的原因。
  2. 在使用 cluster sharding 时良好分配 actors 的关键是提供良好的 extractShardId 和足够的分片。根据您的示例,每个节点很可能不会正好有 5000 个参与者,但它可能足够接近了。我建议从大量的分片开始,比您计划使用的集群实例的数量要多得多,100 是可以开始的。这加上一个好的 extractShardId 将在集群节点之间大致平均分配您的负载。
  3. 问的很好,你说的对。分片系统使用 extractShardIdextractEntityId 的组合将您的消息路由到正确的 actor 实例。然后那个演员可以回复 sender().

备注:

  • 以上所有内容也可以通过集群客户端正常工作。
  • 根据您的需要,可能不需要从一开始就启动所有参与者。当您向尚不存在的分片 actor 发送消息时,该 actor 将由集群分片系统自动透明地启动。那时你可以恢复它的状态。这个加上自动钝化可以帮你节省很多资源!