2013-01-11 14 views
8

Chcę zrobić coś takiego.Jak uzyskać absolutny adres URL zdalnego aktora z wnętrza aktora?

Aktor A:

actorB ! "info" 

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

     } 
} 

Aktor B: (ten wdrożony zdalnie)

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

    } 

} 

chcę wrócić mi Akka ciąg: //10.4.20.40: 2555/slave/użytkownik/slaverunner. Ale otrzymuję tylko akka: // slave. Jak uzyskać zdalny host i port? . Własności host, port i hostPort na obiekcie adresowej dont powrócić niczego

Odpowiedz

7

Jeśli zadzwonisz

sender.path.toString 

w aktora A dostaniesz adres nadawcy. Nie musisz więc przekazywać adresu innemu systemowi aktorskiemu, o ile możesz wysłać do niego wiadomość.

Akka nie da ci zdalnej ścieżki dla aktora w systemie lokalnym, dlatego self.path.address.toString w aktor B nie będzie działać.

Jeśli naprawdę chcesz wysłać hosta i port z B na A, musisz uzyskać dostęp do RemoteActorRefProvider przez ExtendedActorSystem. Oficjalnym sposobem na to jest Extension. Na przykład:

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 

I to daje dokładny adres, który trzeba komunikować się zdalnie z B.

(uwaga ten kod działa z Akka 2.0.x. W 2.1.x można uniknąć dzieje przez RemoteActorRefProvider przy użyciu system.provider.getDefaultAddress)

W Akce jeśli używasz konstruowania adresy aktor w ten sposób do pracy z actorFor to trzeba się upewnić, że nazwy hostów dopasować dokładnie.

Na przykład jeśli ActorSystem myśli gospodarz jest foo.bar.com, a następnie będzie ignorować wiadomości wysłane przez zdalnego hosta do actorFor("akka://[email protected]:2555/user/slaverunner")

+0

Należy zdecydowanie nie robić: „context.system.asInstanceOf [ExtendedActorSystem] .provider.asInstanceOf [RemoteActorRefProvider] .transport.address ". Wszelkie ślepe rzucanie jest całkowicie nieobsługiwane. Przeczytaj dokumentację opisującą, jak wykonać to zadanie, zapewniam Cię, że jest tam. –

+0

Pozbyłem się nieobsługiwanego przesyłania za pomocą 'RemoteActorRefProvider' i dodałem przykład dla Akka 2.1. – sourcedelica

+0

Właśnie wymieniono wyjątek ClassCastException dla elementu MatchError. Co zrobi kod, zmieniają się szczegóły realizacji? –

1

mam to owinięty String:

ConfigString("akka://[email protected]:2552") 

Korzystanie system.settings:

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

Aktor był "root" aktor, w schemat tkaniny zaproponowany przez Viktora Klanga w dyskusji grupy dyskusyjnej dotyczącej "ustalenia, czy aktor nie żyje". Powstał w ten sposób:

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

z ActorSystem który został stworzony tak:

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://[email protected]:2552" 
     }  
     } 
    } 
    remote { 
     netty { 
     hostname = "127.0.0.1" 
     port = 2552 
     } 
    } 
    } 
} 
""").getConfig("serverconf")) 

Testowane Scala 2.9.2 rEPL z Akka 2.0.3, że nadal używać.

rozpakować wartość rzeczywistą korzystając Config docs tutaj: http://typesafehub.github.com/config/v0.3.0/

+0

lepiej pomysły pozyskiwania adresów globalnych może przynieść dyskusję na nowy poziom =) – idonnie

1

Zobacz public address of an actorsystem. Przeczytaj całą dyskusję i zauważ, że "normalnie" nie musisz chwytać hosta/portu.

+0

Patrik, próbowałem zbudować PoC, w którym uczestniczyli aktorzy-niewolnicy rejestrujący się u mistrza. To był mój przypadek użycia – questionersam

1

Dla nowszych wersjach Akka (2.1+) użyj:

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 jest to, czego szukali:

chcę wrócić mi ciąg Akka: //10.4.20.40:2555/slave/user/slaverunner

Więcej nowości Akka wersje (2.5.3) użyj:

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) 
} 
Powiązane problemy