2011-06-01 7 views
13

Soy bastante nuevo en Akka y no pude encontrar la respuesta en el manual de referencia.Secuencia de envío de mensajes en akka actors

Supongamos que tenemos agentes remotos distribuidos en el grupo de 3 máquinas (A, B, C), donde un actor vive en cada máquina y otros han actorRef a otros 2, es decir:

Machine A: 
A (real actor) 
-> B (ref) 
-> C (ref) 

Machine B: 
-> A (ref) 
B (real actor) 
-> C (ref) 

Machine C: 
-> A (ref) 
-> B (ref) 
C (real actor) 

Actor A ejecuta código siguiente:

bRef ! msg1 
bRef ! msg2 

Actor B ejecuta código siguiente en el controlador de mensajes:

case msg1 => 
    cRef ! msg3 
    aRef ! msg4 

Actor C ejecuta código siguiente en el controlador de mensajes:

case msg3 => 
    aRef ! msg5 

¿Puedo hacer las siguientes suposiciones (si lo hay):

  1. el actor B se msg1 antes de que llegue msg2

  2. actor A obtiene msg5 antes de obtener msg4

Y la pregunta de seguimiento que probab conduce a la comprensión de lo anterior: Es mensaje enviado por el! operador a través de la red de manera realmente asíncrona o ¿espera hasta que el buzón receptor lo obtenga? Es decir hace la línea

bRef ! msg1 

bloque hasta que el actor B recibe el mensaje en su buzón de correo o se desovar el hilo que se encarga de la entrega y continúe ejecutando

bRef ! msg2 

incluso antes de que sabe que el actor B consiguió msg1?

Respuesta

7

Para (1) usted tiene la garantía de que msg1 será enrutado por el despachador antes de msg2. Lo que sucede realmente una vez que se ponen en cola depende realmente del despachador que use: http://akka.io/docs/akka/1.1.2/scala/dispatchers.html, pero en su caso, siempre que B pueda aceptar ambos mensajes, siempre recibirá msg1 antes de msg2.

Para (2), no, no tiene esta garantía. Los ! El método vuelve tan pronto como el despachador encola el mensaje, no cuando el mensaje es aceptado por el buzón del actor objetivo. El envío se realiza en otro hilo y está sujeto a todo tipo de condiciones de carrera.

¡Ha enviado el mensaje por! operador a través de la red de manera realmente asíncrona o ¿espera hasta que el buzón receptor lo obtenga?

Puede usar un BoundedMailbox con actores locales para mostrar que enviar mensajes a los despachadores es asincrónico.:

class TestActor extends Actor { 
    val mailboxCapacity = BoundedMailbox(capacity = 1) 
    self.dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("test", 1, mailboxCapacity).build 

    def receive = { 
    case x: String => 
     Thread.sleep(1000) 
     println("Received message") 
    case _ => 
    } 
} 

val t = Actor.actorOf[TestActor] 
t.start() 

t ! "one"; t ! "two"; t ! "three"; println("Main thread"); 

Lienzo:

scala>  t ! "one"; t ! "two"; t ! "three"; println("Main thread"); 
Received message 
Main thread 

scala> Received message 
Received message 

Lo que significa que la ejecución de código en el hilo principal continúa incluso antes de saber si es o no el mensaje nunca será entregado. En este caso, el envío del mensaje fácilmente podría haber expirado si configuramos pushTimeout en el despachador e hicimos que Thread.sleep espere más tiempo que el tiempo de espera excedido.

comparar esto con el uso !!:

scala>  t !! "one"; t !! "two"; t !! "three"; println("test"); 
Received message 
Received message 
Received message 
test 

Por lo tanto, con esto en mente. La forma de lograr (2) sería:

case msg1 => 
    cRef !! msg3 
    aRef ! msg4 
+0

No ha direccionado realmente 1. y 2., aunque podría inferir que 2. no se ajusta a lo que ha mostrado. Esto no aborda 1. incluso tangencialmente, sin embargo. –

+0

Tienes razón. Modifiqué mi respuesta para responder a la pregunta específica que estaba respondiendo. –

+0

¿Estás seguro de que para lograr (2) no tengo que cambiar el código del actor C a aRef !! msg5? – Grozz

1

Erlang te ofrece la primera garantía, pero no la segunda. Akka también podría darle la primera garantía, pero ciertamente no le dará la segunda garantía.

No conozco la respuesta a tu pregunta de seguimiento.

Cuestiones relacionadas