2013-01-11 11 views
8

Voglio fare qualcosa di simile.Come ottengo l'url assoluto di un attore remoto dall'interno dell'attore?

Attore A:

actorB ! "info" 

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

     } 
} 

Attore B: (questo distribuito in remoto)

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

    } 

} 

voglio per tornare me l'Akka stringa: //10.4.20.40: 2555/slave/utente/slaverunner. Ma quello che ottengo è solo Akka: // schiavo. Come posso ottenere l'host e la porta remoti? . La proprietà host, la porta e hostport sull'oggetto indirizzo Non restituiscono nulla

risposta

7

Se si chiama

sender.path.toString 

in attore A si otterrà l'indirizzo del mittente. Quindi non è necessario passare l'indirizzo a un altro sistema di attori fintanto che è possibile inviare un messaggio ad esso.

Akka non ti darà un percorso remoto per un attore nel sistema locale, motivo per cui self.path.address.toString nell'attore B non funzionerà.

Se si desidera realmente inviare l'host e la porta da B a A, è necessario accedere a RemoteActorRefProvider tramite ExtendedActorSystem. Il modo ufficiale per farlo è attraverso un Extension. Per esempio:

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 

E che vi darà l'indirizzo esatto che avete bisogno di comunicare a distanza con B.

(notare che questo codice funziona con Akka 2.0.x. In 2.1.x si può evitare di andare attraverso RemoteActorRefProvider utilizzando system.provider.getDefaultAddress)

In Akka se si utilizza la costruzione indirizzi attore in questo modo per l'utilizzo con actorFor quindi è necessario assicurarsi che i nomi host corrispondono esattamente.

Per esempio se l'ActorSystem pensa l'host è foo.bar.com, allora sarà ignorare i messaggi inviati da un host remoto per actorFor("akka://[email protected]:2555/user/slaverunner")

+0

Si dovrebbe sicuramente non fare: "context.system.asInstanceOf [ExtendedActorSystem] .provider.asInstanceOf [RemoteActorRefProvider] .transport.address". Qualsiasi e tutti i casting ciechi sono completamente non supportati. Si prega di leggere la documentazione per la descrizione su come svolgere questo compito, vi assicuro che è lì dentro. –

+0

Eliminato il cast non supportato tramite 'RemoteActorRefProvider' e un esempio aggiunto per Akka 2.1. – sourcedelica

+0

Hai appena scambiato un ClassCastException per un errore MatchError. Quale sarà il codice che farà cambiare i dettagli di implementazione? –

1

ho ottenuto questo avvolto String:

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

Utilizzando system.settings:

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

attore era un attore di "root", in uno schema di tessuto suggerito da Viktor Klang in una discussione del gruppo di posta riguardante "determinare se l'attore è morto". E 'stato creato in questo modo:

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

da ActorSystem che è stato creato in questo modo:

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")) 

Testato a Scala 2.9.2 REPL con Akka 2.0.3 che ho ancora utilizzare.

Separa valore effettivo utilizzando Config docs qui: http://typesafehub.github.com/config/v0.3.0/

+0

meglio le idee di ottenere indirizzi globale potrebbe portare la discussione ad un nuovo livello =) – idonnie

1

Vedi public address of an actorsystem. Leggi la discussione completa e nota che "normalmente" non è necessario prendere l'host/porta.

+0

Patrik, stavo cercando di costruire un PoC, che coinvolgeva attori schiavi che si registravano con il maestro. Quello era il mio caso d'uso – questionersam

1

per le versioni recenti Akka (2.1+) utilizzare questo:

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)) 

il remotePath è ciò che stavate cercando:

voglio che tornare mi stringa Akka: //10.4.20.40:2555/slave/user/slaverunner

Per i più recenti Akka versioni (2.5.3) Utilizzare questo:

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) 
} 
Problemi correlati