Akka Cluster Client 能否向不在初始联系中的集群节点发送消息?

Can Akka Cluster Client Send Messages to Cluster Nodes Not in Initial Contacts?

我正在尝试使用 Akka 2.3.14 创建各种服务的 Akka 集群。到目前为止,我的所有 "services" 都集中在一个跨多个节点集群的工件中,但现在我正试图将这个工件分解为多个服务,这些服务都存在于同一个集群上。

因此,在分解时,我们将其设计为集群上的任何节点都将首先尝试连接到种子节点。如果没有种子节点,它将查看它是否是 运行 作为种子节点的候选者(如果它在种子节点可以在的同一主机上),在这种情况下它将获取一个开放种子节点端口,成为种子节点。所以从这个意义上说,集群中的任何服务都可以成为种子节点。

至少,这是个主意。我们 API 进入此系统 运行ning 作为一项单独的服务将 ClusterClient 实施到此系统中。 initialContacts 设置为与种子节点相同。问题是我可以通过 ClusterClient 向其发送消息的唯一接待员角色是种子节点上的角色。

这里有一个例子,如果有帮助的话。假设我有一个 String Service 和一个 Double Service,每个服务的接待员分别是一个 StringActor 和一个 DoubleActor。现在假设我有一个客户端服务,它将 StringMessages 和 DoubleMessages 发送到 StringActor 和 DoubleActor

为了简单起见,假设我有两个节点,server1 和 server2 然后:

seed-nodes = ["akka.tcp://system@server1:2773", "akka.tcp://system@server2:2773"]

我的 ClusterClient 将像这样初始化:

system.actorOf(
    ClusterClient.props(
        Set(
            system.actorSelection("akka.tcp://system@server1:2773/user/receptionist"),
            system.actorSelection("akka.tcp://system@server2:2773/user/receptionist")
        )
    ),     
    "clusterClient"
)

以下是我遇到的情况:

  1. 如果 StringServices 首先在两个服务器上启动,那么来自客户端服务的 DoubleMessages 就会消失在以太中。
  2. 如果 DoubleServices 首先在两个服务器上启动,那么来自客户端服务的 StringMessages 就会消失在以太中。
  3. 如果StringService先在serverX上启动,DoubleService先在serverY上启动,那么所有的StringMessages都会发送到serverX,所有的DoubleMessages都会发送到serverY,这没有上面的情况那么糟糕,但是这意味着它并没有真正缩放。

这不是我所期望的,这可能只是我的代码中的一个缺陷,所以我想知道这是否是预期的行为。如果没有,那么是否有另一个 Akka 概念可以帮助我解决这个问题?

可以说,我可以只将一种服务类型作为我的入口点,例如可以接受 StringMessages 或 DoubleMessages 的 RoutingService,然后将其发送到正确的服务。但是,如果客户端服务只能将消息发送到初始联系人中的 RoutingService 实例,那么我无法动态扩展 RoutingService,因为无论我添加多少节点,客户端服务都只能发送到初始联系人。

我也在考虑在我的客户端服务中订阅 ClusterEvents,看看我是否可以在集群中启动节点时从我的集群客户端添加和删除初始联系人,但我不确定这是否可行可以的,感觉应该有更好的解决办法

这是我在进行更多故障排除后发现的,以防对其他人有所帮助:

ClusterClient 将尝试按顺序连接到初始联系人,然后仅通过该连接发送消息。如果您在每个节点上部署不同的服务,您将会遇到问题,因为从 ClusterClient 发送的消息只会发送到它建立连接的节点。这样,你可以把ClusterClient想象成一个合法的客户端,它会连接到你给它的一个URL,然后通过那个URL.

继续和服务器通信。

阅读 Distributed Workers 示例,我意识到我的前端,或者在本例中是我的路由服务,实际上应该是集群的一部分,而不是充当客户端。为此,我改用了 DistributedPubSub 方法。