代码之家  ›  专栏  ›  技术社区  ›  joesan

Akka有状态参与者跨节点复制

  •  2
  • joesan  · 技术社区  · 8 年前

    我有一个Akka应用程序,我使用Play Framework作为Web应用程序运行。当我启动这个应用程序时,我创建了一组参与者,这些参与者具有状态。这些参与者响应外部消息并改变状态(我使用上下文改变状态。变成(…)机制)。

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

    我这里有几个问题:

    1. 我如何运行更多的Play Framework web应用程序实例,记住我有状态的参与者!我想确保,如果某个实例发生故障,该实例中有状态的参与者将与故障前的状态一起复活。Akka集群切分会是一种方式吗?

    2. 假设我的应用程序中有10000个这样的有状态参与者,那么我如何利用Akka集群切分,使这10000个参与者中的并非所有参与者都在同一个节点上运行?我的意思是,如何让前5000名演员在node1上运行,而下5000名演员在node2上运行?现在,我对单个实例所做的是,当我启动应用程序时,我读取数据库,并使用数据在每个数据库行启动一个actor实例。

    3. ask模式如何与集群切分一起工作?我发送到Shard区域的任何消息都将路由到相应的Actor实例,但是请求特定Actor的消息又如何呢?它也会以同样的方式工作吗?我向参与者请求消息,我将我的ask请求发送到Shard区域,该Shard区域将此消息转发给相应的参与者?这是正确的吗?

    有什么建议吗?

    1 回复  |  直到 8 年前
        1
  •  1
  •   Frederic A.    8 年前

    有两种不同的方法可以设置akka群集:

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

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

    您没有明确说明参与者的状态当前是如何持续的。是否所有状态更改都以某种方式写回数据库?如果你什么都没有,Akka坚持可能会帮助你。

    对于您的问题:

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

    备注:

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