2

我有一个在 Android 设备上运行的 Akka 系统,它通过 Akka Remoting 与服务器上的 Akka 系统通信。

Android 设备可能会获得任何 IP 地址,IP 可能会在应用程序运行时更改,并且 IP 可能无法从服务器访问。因此,我在 Android 设备上使用akka.remote.netty.hostname = "0.0.0.0"和配置了 Akka akka.remote.netty.port = 8000

Android Akka 系统获取到服务器上的一个 Actor 的引用,向它发送消息,服务器上的 Actor 记录 sender() actorRef 并不断向它发送消息。当服务器和 Android 设备都在同一个 wlan 上时,并且当它们通过互联网通过 GPRS 通话时,此方法有效。

现在我正在仔细研究连接丢失和重新连接。我一直关注的场景是这样的:

  • Android 设备和服务器都在一个 wlan 上。
  • Android 设备向服务器发送消息。
  • Android 上的 Akka 远程处理产生RemoteClientStarted.
  • 服务器上的 Akka 远程处理产生RemoteClientStartedRemoteServerClientConnected.
  • 然后我关掉安卓上的wlan,等几秒再打开。在这期间不会尝试向服务器发送任何消息。
  • Android 上的 Akka 远程处理产生RemoteClientShutdownRemoteClientError(ETIMEDOUT)
  • 服务器上的 Akka 远程处理什么也没说。
  • Android 向服务器发送消息。
  • 服务器产生RemoteServerClientConnected并接收消息。
  • 服务器尝试向Android 发送一条消息(以下问题称为ARemoteServerError ),并产生: , RemoteServerClientDisconnected, RemoteClientShutdown, RemoteServerClientClosed
  • Android 永远不会从服务器获取消息。
  • 服务器尝试发送另一条消息,但 AkkasRemoteClient说:
    • [PassiveRemoteClient@akka://xxx@0.0.0.0:8000] 已关闭
    • 启动到 [akka://xxx@0.0.0.0:8000|/0.0.0.0] 的远程客户端连接
    • RemoteClientError@akka://vts@0.0.0.0:8000: 错误[...

最后一个错误似乎来自 Akka Remote 想要创建一个新ActiveRemoteClient的而不是重用现有的PassiveRemoteClient. 我猜这又是因为服务器在看到错误/断开连接/关闭/客户端关闭之前观察了 RemoteServerClientConnected 事件。

现在的问题:

  1. 在这种情况下发送消息 A 时,如何让服务器重用PassiveRemoteClient来自 Android 设备的最后一个传入连接 ( )?
  2. 如何指示服务器不要尝试连接回客户端?

版本:

  • 安卓:15(4.0.3)
  • 阿卡:2.1
  • Java:1.6 64位
  • 斯卡拉:2.10.1
  • 网:3.5.8
4

1 回答 1

7

这可能不是您一直希望的答案,但它就是这样(我是 Akka 技术负责人)。

Akka 远程处理旨在在充当对等点的系统之间工作。开发背后的驱动力是构建集群支持,该支持开始出现在 2.1 版中,并且将从 2.2 版开始得到官方支持并进一步开发。这有几个重要的后果:

  • ActorRefs应该是位置透明的,这意味着无论您在哪里使用它们,它们的工作方式都是一样的,因此每个节点都需要能够连接到给定引用指向的节点。
  • Akka 节点之间的通信基本上是对称的,即使您对它的使用可能不是。
  • 传递ActorRef作为进行对话的一种手段意味着通过引用指向的实体需要保持可用,否则通信将失败;并且保持可用意味着“在参考指向的同一位置”。

这对您的场景意味着,您最好不要使用普通的远程处理来耦合您的演员系统,而是使用其他支持您遭受的短期关联的东西。例如,您可以将服务器公开为 REST 服务,或者您可以使用 Akka IO 层仅使用裸 TCP(甚至 UDP)。在服务器端处理端点的actor中,您可以识别同一客户端是否从不同的网络位置与您交谈,缓冲回复消息,将外部actor伪装成本地代理actor等。使用此方案,您甚至可以构建通过不可靠的通道(使用 ACKing)进行可靠的消息传递,美妙之处在于,在服务器(可能是集群)内,所有通信都可以正常工作,因为如何与客户端通信的问题部分被封装在一个地方。

长话短说:您的用例不是开箱即用的普通 Akka 远程支持的用例。

于 2013-04-22T12:38:16.643 回答