【问题标题】:How do I get the absolute remote actor url from inside the actor?如何从演员内部获取绝对远程演员网址?
【发布时间】:2012-12-26 14:52:35
【问题描述】:

我想做这样的事情。

演员甲:

    actorB ! "info"

     def receive()={
     case _ => {
          println("Remote address is "+ _)

        }
}

演员 B :(远程部署)

def receive()={
 case "info" => {
      sender tell self.path.address.toString

    }

}

我希望它返回字符串 akka://10.4.20.40:2555/slave/user/slaverunner 。但我得到的只是 akka://slave。如何获取远程主机和端口? .地址对象上的属性 host、port 和 hostport 不返回任何内容

【问题讨论】:

    标签: scala akka


    【解决方案1】:

    如果你打电话

    sender.path.toString
    

    在演员 A 中,您将获得发件人的地址。因此,只要您可以向它发送消息,您就不需要将地址传递给另一个参与者系统。

    Akka 不会为您提供本地系统中演员的远程路径,这就是演员 B 中的 self.path.address.toString 不起作用的原因。

    如果您真的想将主机和端口从 B 发送到 A,那么您需要通过 ExtendedActorSystem 访问 RemoteActorRefProvider。官方的做法是通过Extension。例如:

    class MyExtensionImpl(system: ExtendedActorSystem) extends Extension {
      def address = system.provider match {
        case rarp: RemoteActorRefProvider => rarp.transport.address
        case _ => system.provider.rootPath.address
      }
    }
    
    object MyExtension extends ExtensionKey[MyExtensionImpl]
    
    val address = MyExtension(system).address
    

    这将为您提供与 B 进行远程通信所需的确切地址。

    (请注意,此代码适用于 Akka 2.0.x。在 2.1.x 中,您可以使用 system.provider.getDefaultAddress 避免通过 RemoteActorRefProvider

    在 Akka 中,如果您使用这种方式构建参与者地址以与 actorFor 一起使用,那么您需要确保主机名完全匹配。

    例如如果ActorSystem认为主机是foo.bar.com,那么它将忽略远程主机发送给actorFor("akka://slave@foo:2555/user/slaverunner")的消息

    【讨论】:

    • 你绝对不应该这样做:“context.system.asInstanceOf[ExtendedActorSystem].provider.asInstanceOf[RemoteActorRefProvider].transport.address”。完全不支持任何和所有盲投。请阅读文档以获取有关如何完成此任务的说明,我向您保证它就在那里。
    • 通过RemoteActorRefProvider 摆脱了不支持的强制转换,并为 Akka 2.1 添加了示例。
    • 您刚刚将 ClassCastException 换成了 MatchError。实现细节发生变化时,代码会做什么?
    • 基于扩展系统(因为我已经看到很多system.asInstanceOf[ExtendedActorSystem] 漂浮在周围)我假设所有的演员系统将永远是ExtendedActorSystems。很公平。
    • ActorSystem 也是 ExtendedActorSystem 是一个实现细节。使用 Extension SPI 获取 ExtendedActorSystem。干杯,
    【解决方案2】:

    对于最近的 akka 版本(2.1+),请使用:

    class RemoteAddressExtensionImpl(system: ExtendedActorSystem) extends Extension {
      def address = system.provider.getDefaultAddress
    }
    
    object RemoteAddressExtension extends ExtensionKey[RemoteAddressExtensionImpl]
    
    val remoteAddr = RemoteAddressExtension(context.system).address
    val remotePath = self.path.toStringWithAddress(remoteAddr))
    

    remotePath 是您要查找的内容:

    我希望它返回字符串 akka://10.4.20.40:2555/slave/user/slaverunner

    对于更新的 akka 版本 (2.5.3),请使用:

    class RemoteAddressExtensionImpl(system: ExtendedActorSystem) extends Extension {
      def address = system.provider.getDefaultAddress
    }
    
    object RemoteAddressExtension extends ExtensionId[RemoteAddressExtensionImpl]
    with ExtensionIdProvider {
      override def lookup = RemoteAddressExtension
      override def createExtension(system: ExtendedActorSystem) = new RemoteAddressExtensionImpl(system)
      override def get(system: ActorSystem): RemoteAddressExtensionImpl = super.get(system)
    }
    

    【讨论】:

    • toStringWithAddress 代替toSerializationFormatWithAddress
    【解决方案3】:

    我得到了这个包装String

     ConfigString("akka://serversys@127.0.0.1:2552")
    

    使用system.settings

    context.system.settings.config.getValue("akka.actor.deployment.\"/root\".remote")
    

    Actor 是“根”actor,这是 Viktor Klang 在邮件组讨论“确定 actor 是否死亡”时建议的结构方案。它是这样创建的:

    lazy val rootActor = actorSystem.actorOf(Props[Root], "root")
    

    来自ActorSystem 是这样创建的:

    lazy val actorSystem = ActorSystem("serversys", ConfigFactory.parseString(""" 
    akka {
      loglevel = "DEBUG"
      actor {
        provider = "akka.remote.RemoteActorRefProvider"
      }
      remote {
        transport = "akka.remote.netty.NettyRemoteTransport"
      }
    }
    serverconf {
      include "common"
      akka {
        actor {
          deployment {
            /root {
              remote = "akka://serversys@127.0.0.1:2552"
            }    
          }
        }
        remote {
          netty {
            hostname = "127.0.0.1"
            port = 2552
          }
        }
      }
    }
    """).getConfig("serverconf"))
    

    在 Scala 2.9.2 REPL 和我仍在使用的 Akka 2.0.3 中测试。

    在此处使用 Config 文档解包实际值:http://typesafehub.github.com/config/v0.3.0/

    【讨论】:

    • 获得全球地址的任何更好的想法都可以将讨论带到一个新的水平=)
    【解决方案4】:

    public address of an actorsystem。 阅读完整的讨论,并注意“通常”您不需要获取主机/端口。

    【讨论】:

    • Patrik,我正在尝试构建一个 PoC,其中涉及奴隶演员向主人注册自己。那是我的用例
    猜你喜欢
    • 2012-03-31
    • 2010-10-07
    • 2013-11-22
    • 2019-04-23
    • 2021-07-05
    • 1970-01-01
    • 2014-05-28
    • 2012-05-09
    • 2012-08-08
    相关资源
    最近更新 更多