gpt4 book ai didi

playframework - 集群中 Akka Actor 的发现

转载 作者:行者123 更新时间:2023-12-03 06:54:16 25 4
gpt4 key购买 nike

最近我一直在尝试理解 Akka 和基于 Actor 的系统的概念。虽然我现在对 Akka 基础知识有了很好的了解,但在集群和远程 Actor 方面,我仍然在一些问题上遇到困难。

我将尝试使用 WebSocket chat example that comes with Play Framework 2.0 来说明该问题:有一个参与者持有 WebSocket 并保存当前连接的用户列表。 Actor 在技术上和逻辑上基本上代表了聊天室。只要单个服务器上运行一个聊天室,这种方法就可以正常工作。

现在我试图理解当我们谈论在服务器集群上运行的许多动态聊天室(可以随时打开/关闭新房间)(单个节点是根据当前需求添加或删除)。在这种情况下,用户 A 可以连接到服务器 1,而用户 B 连接到服务器 2。两者可能正在同一个聊天室中交谈。在每个服务器上仍然会有一个参与者(对于每个聊天室?),它持有 WebSocket 实例以接收事件(消息)并将其发布给正确的用户。但从逻辑上讲,服务器 1 或服务器 2 上应该只有一个聊天室参与者来保存当前连接的用户(或类似任务)的列表。

您将如何实现这一目标,最好是“纯 akka”,而不添加像 ZeroMQ 或 RabbitMQ 这样的额外消息系统?

这是我到目前为止所想到的,请让我知道这是否有意义:

  1. 用户 A 连接到服务器 1,并分配一个参与者来保存其 WebSocket。
  2. 参与者检查(使用路由器?EventBus?其他什么?)事件聊天室的“聊天室参与者”是否存在于任何连接的集群节点上。因为它不这样做,所以它会以某种方式请求创建一个新的聊天室参与者,并将向该参与者发送和接收 future 的聊天消息。
  3. 用户 B 连接到服务器 2,并且也为其 WebSocket 分配了一个参与者。
  4. 它还会检查所请求的聊天室的参与者是否存在于某处,并在服务器 1 上找到它。
  5. 服务器 1 上的聊天室参与者现在充当给定聊天室的中心,向所有“已连接”的聊天成员参与者发送消息并分发传入的消息。

如果服务器 2 出现故障,则必须以某种方式在服务器 2 上重新创建/移动聊天室参与者,尽管这不是我现在主要关心的问题。我最想知道如何使用 Akka 的工具集来完成这种动态发现参与者如何在各种基本上独立的机器上传播的情况。

我已经查看 Akka 的文档很长一段时间了,所以也许我在这里错过了明显的内容。如果是这样,请赐教:-)

最佳答案

我正在开发一个私有(private)项目,它基本上是聊天室示例的一个非常扩展的版本,我也遇到了 akka 和整个“去中心化”思维的启动问题。所以我可以告诉你我是如何“解决”我的扩展聊天室的:

我想要一个可以轻松部署多次而无需太多额外配置的服务器。我使用 Redis 作为所有开放用户 session (其 ActorRef 的简单序列化)和所有聊天室的存储。

服务器具有以下参与者:

  • WebsocketSession:它保持与一个用户的连接并处理来自用户的请求并转发来自系统的消息。
  • ChatroomManager:这是中央广播器,部署在每个实例上服务器的。如果用户想要向聊天室发送消息,WebSocketSession-Actor 会将所有信息发送到 ChatroomManager-Actor,然后 ChatroomManager-Actor 将该消息广播给聊天室的所有成员。

这是我的程序:

  1. 用户 A 连接到分配新 WebsocketSession 的服务器 1。该 actor 将该 actor 的绝对路径插入到 redis 中。
  2. 用户 A 加入聊天室 X,该聊天室还将他的绝对路径(我将其用作用户 session 的唯一 ID)插入到 Redis 中(每个聊天室都有一个“连接”集)
  3. 用户 B 连接到服务器 2 -> redis
  4. 用户 B 加入聊天室 X -> redis
  5. 用户 B 向聊天室 X 发送消息,如下所示:用户 B 通过 Websocket 将消息发送给他的 session 参与者, session 参与者(经过一些检查)将参与者消息发送给 ChatroomManager。该actor实际上从redis检索聊天室的用户列表(与akka的actorFor方法使用的绝对路径),然后将消息发送到每个 session actor。然后,这些 session 参与者写入他们的 websocket。

在每个 ChatroomManager-actor 中,我都会进行一些 ActorRef 缓存,这会提高速度。我认为这与您的方法不同,特别是这些 ChatroomManager 处理所有聊天室的请求。但是,一个聊天室只有一个 Actor 是一种单点故障,我想避免这种情况。此外,这会导致更多消息,例如:

  • 用户 A 和用户 B 位于服务器 1 上。
  • 聊天室 X 位于服务器 2 上。

如果用户 A 想要与用户 B 交谈,他们都必须通过服务器 1 上的聊天室参与者进行通信。

此外,我还使用 akka 的功能(例如(循环)路由器)在每个系统上创建 ChatroomManager-actor 的多个实例来处理许多请求。

我花了几天时间结合序列化和 Redis 设置整个 akka 远程基础设施。但现在我可以创建任意数量的服务器应用程序实例,这些实例使用 redis 来共享 ActorRef(使用 ip+port 序列化为绝对路径)。

这可能会对您有进一步的帮助,我愿意回答新问题(请不要问我的英语;)。

关于playframework - 集群中 Akka Actor 的发现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10073446/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com