我有一个在 Android 设备上运行的 Akka 系统,它通过 Akka Remoting 与服务器上的 Akka 系统通信。
Android 设备可以获得任何 IP 地址,IP 可能会在应用程序运行时发生变化,并且 IP 可能无法从服务器访问。因此,我在 Android 设备上使用 akka.remote.netty.hostname = "0.0.0.0"
和 akka.remote.netty.port = 8000
配置了 Akka。
Android Akka 系统在服务器上获取一个 actor 的引用,向它发送消息,服务器上的 Actor 记录 sender() actorRef 并不断向它发送回消息。这适用于服务器和 Android 设备都在同一个 wlan 上,并且当它们通过互联网通过 GPRS 通话时。
现在我正在仔细研究连接丢失和重新连接。我一直关注的场景是这样的:
- Android 设备和服务器都在 wlan 上。
- Android 设备向服务器发送消息。
- Android 上的 Akka 远程处理生成
RemoteClientStarted
。 - 服务器上的 Akka 远程处理生成
RemoteClientStarted
和RemoteServerClientConnected
。 - 然后我关闭 Android 上的无线局域网,等待几秒钟,然后再次打开。在此期间不会尝试向服务器发送任何消息。
- Android 上的 Akka 远程处理产生
RemoteClientShutdown
和RemoteClientError
(ETIMEDOUT) - 服务器上的 Akka 远程处理什么也没说。
- Android 向服务器发送消息。
- 服务器生成
RemoteServerClientConnected
并接收消息。 - 服务器尝试向 Android 发送消息(以下问题称它为 A),并产生:
RemoteServerError
、RemoteServerClientDisconnected
、RemoteClientShutdown
,RemoteServerClientClosed
。 - Android 永远不会从服务器获取消息。
- 服务器尝试发送另一条消息,但是 Akkas
RemoteClient
说:- [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 事件。
现在问题:
- 在这种情况下发送消息 A 时,如何让服务器重用来自 Android 设备的最后一个传入连接 (
PassiveRemoteClient
)? - 如何指示服务器永远不要尝试连接回客户端?
版本:
- 安卓:15 (4.0.3)
- Akka :2.1
- Java:1.6 64 位
- 斯卡拉:2.10.1
- Netty:3.5.8
最佳答案
这可能不是您一直希望得到的答案,但就是这样(我是 Akka 技术主管)。
Akka 远程处理旨在在充当对等方的系统之间工作。开发背后的驱动力是构建集群支持,它开始出现在 2.1 版中,并将从 2.2 版开始正式支持并进一步开发。这有几个重要的后果:
-
ActorRefs
应该是位置透明的,这意味着无论您在哪里使用它们,它们的工作方式都是一样的,因此每个节点都需要能够连接到给定引用指向的节点。 - Akka 节点之间的通信基本上是对称的,即使您对它的使用可能不是。
- 路过
ActorRef
作为进行对话的手段意味着通过引用指向的实体需要保持可用,否则通信将失败;保持可用意味着“在引用指向的相同位置”。
这对您的场景意味着您最好不要使用简单的远程处理来耦合您的参与者系统,而是使用其他支持您遭受的短期关联的东西。例如,您可以将服务器公开为 REST 服务,或者您可以使用 Akka IO 层使用裸 TCP(甚至 UDP)。在处理服务器端端点的 actor 中,您可以识别同一个客户端是否从不同的网络位置与您交谈、缓冲回复消息、伪装成本地代理 actor 后面的外部 actor 等。使用此方案,您甚至可以内置通过不可靠的 channel (使用 ACKing)进行可靠的消息传递,美妙之处在于在服务器(可能是集群)内所有通信都正常工作,因为如何与客户端交谈的问题部分被封装在一个地方。
长话短说:您的用例不是开箱即用的普通 Akka 远程处理所支持的用例。
关于android - Akka Remoting 是否仅支持单向连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16094079/