【问题标题】:Does Akka Remoting support one-way only connections?Akka Remoting 是否支持单向连接?
【发布时间】:2013-04-12 05:23:31
【问题描述】:

我有一个在 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 远程处理产生 RemoteClientStartedRemoteServerClientConnected
  • 然后我关闭Android上的无线局域网,等待几秒钟再打开。在这期间不会尝试向服务器发送任何消息。
  • Android 上的 Akka 远程处理产生 RemoteClientShutdownRemoteClientError (ETIMEDOUT)
  • 服务器上的 Akka 远程处理什么也没说。
  • Android 向服务器发送消息。
  • 服务器生成RemoteServerClientConnected 并接收消息。
  • 服务器尝试向 Android 发送消息(以下问题称为 A),并产生:RemoteServerErrorRemoteServerClientDisconnectedRemoteClientShutdownRemoteServerClientClosed
  • 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 事件。

现在问题:

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

版本:

  • Android:15 (4.0.3)
  • 阿卡:2.1
  • Java:1.6 64 位
  • 斯卡拉:2.10.1
  • 网络:3.5.8

【问题讨论】:

    标签: android networking client-server netty akka


    【解决方案1】:

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

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

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

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

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

    【讨论】:

    • 感谢您的详尽回答,尤其是有关如何使其发挥作用的建议。快速跟进:RemoteTransport 似乎是在 Akka 下实现自己的远程处理的基础。这是无证的,所以我不得不问:这是推荐的方式吗?在即将发布的 Akka 版本中,机制会发生巨大变化吗?
    • RemoteTransport 将在 2.2 中发生变化,虽然可以想象特殊应用程序会创建自己的应用程序,但我们预计这种情况不会经常发生。有很多与演员消息相关的假设可能不符合您的需求。
    • 好吧,我想我会远离RemoteTransport。对于好奇的人:我最终测试了 akka-zeromq。它是针对 zeromq-2.1 构建的,这对我来说是不可接受的。所以我测试了jeromq,它应该是zeromq3的纯java端口。不幸的是,这并没有作为 akka-zeromq 附带的 scala-zeromq-binding 的替代品,但我分叉了 akka-zeromq 模块并用 jeromq 替换了对 scala-zeromq-binding 的依赖。作为一种魅力,但仍需在 Android 上进行测试。
    • 我不在那个名单上。但是请随意复制粘贴:现在没有时间将其打包为独立项目并将其放在 github 上,但我所做的是: 1. 替换所有 org.zeromq... 的导入org.jeromq... 2. 替换了 one 实例的 int 字段访问。除此之外,API 类似。虽然我还没有做太多测试,但我已经初始化了一个 jeromq-actor 并处理了消息,它的行为符合预期。也许您可以为那些不太喜欢摆弄 dll 的人创建一个 akka-jeromq 模块?
    猜你喜欢
    • 2014-09-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2019-08-04
    • 2015-03-22
    相关资源
    最近更新 更多