跨节点的Akka有状态演员复制

时间:2018-04-11 11:56:53

标签: scala akka cluster-computing sharding

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

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

我在这里几乎没有问题:

  1. 如何运行我的Play Framework Web应用程序的几个实例,请记住我有有状态的演员!我想确保如果其中一个实例发生故障,那个实例中的有状态演员就会在状态恢复之前恢复原状。 Akka Cluster Sharding会成为可行的方法吗?

  2. 假设我的应用程序中有10000个这样的有状态角色,我如何利用Akka Cluster Sharding,以至于并非所有10000个actor都在同一个节点中运行?我的意思是如何让第一个5000个actor在node1上运行,接下来的5000个在node2上运行?现在我对单个实例的处理是,当我启动应用程序时,我读取数据库并使用数据为每个数据库行启动一个actor实例。

  3. ask模式如何与群集分片一起使用?我发送到Shard Region的任何消息都将被路由到相应的Actor实例,但是要求来自特定actor的消息呢?它也会以同样的方式工作吗?我要求一个来自Actor的消息,我将我的请求请求发送到Shard Region并且这个shard区域将此消息转发给相应的Actor?这是对的吗?

  4. 有什么建议吗?

1 个答案:

答案 0 :(得分:1)

设置akka群集有两种不同的方法可以做到这一点:

  1. 让所有Play Framework实例按照您的建议构建一个群集
  2. 设置单独的akka​​群集(如果需要,可以将其称为后端),并使用Play Framework实例中的群集客户端连接群集并与群集进行交互
  3. 在上述两种情况下,我都会使用群集分片模块来实现您想要实现的目标。

    你不清楚你的演员的状态目前是如何持久的。是否所有状态更改都以某种方式写回数据库?如果你什么都没有,Akka的坚持可能对你有帮助。

    问题:

    1. 群集分片将负责将您的actor分成多个正在运行的实例,并在实例发生故障时进行迁移。群集分片根本不会处理你的actor的状态。这是一个完全独立的问题,这就是为什么我在上面提到了akka持久性。
    2. 使用cluster sharding时,您的演员分配良好的关键是提供良好的extractShardId和足够的分片。根据您的示例,您很可能每个节点不会有5000个演员,但它可能足够接近。我建议从大量的分片开始,比你计划使用的群集实例的数量多得多,100可以开始。加上一个好的extractShardId将在群集节点之间大致均匀地分配负载。
    3. 问问工作得很好,你说的是对的。分片系统使用extractShardIdextractEntityId的组合将您的消息路由到正确的actor实例。那个演员可以回复sender()
    4. 注意:

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