跨节点的 Akka 有状态执行组件复制



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

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

我在这里有几个问题:

  1. 我怎样才能再运行几个我的 Play 框架 Web 应用程序实例,请记住我有状态的参与者!我想确保如果其中一个实例出现故障,该实例中的有状态参与者会恢复为关闭之前的状态。Akka 集群分片会是要走的路吗?

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

  3. 询问模式如何与集群分片配合使用?我发送到分片区域的任何消息都将路由到相应的Actor实例,但是请求来自特定Actor的消息呢?它也会以同样的方式工作吗?我请求来自Actor的消息,我向分片区域发送询问请求,并且该分片区域将此消息转发给相应的Actor?这是对的吗?

有什么建议吗?

有两种不同的方法可以设置 akka 集群来执行此操作:

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

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

你没有明确说明你的演员的状态当前是如何持续的。是否所有状态更改都以某种方式写回数据库?如果你一无所有,Akka的坚持可能会在这里帮助你。

对于您的问题:

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

笔记:

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

最新更新