akka演员中的消息传递顺序

时间:2011-06-01 13:09:45

标签: scala messages actor akka mq

我对Akka很陌生,在参考手册中找不到答案。

假设我们有远程角色分布在3台机器(A,B,C)的集群中,其中一个角色存在于每台机器上,而其他角色则有actorRef到另外两台机器,即:

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执行以下代码:

bRef ! msg1
bRef ! msg2

Actor B在消息处理程序中执行以下代码:

case msg1 => 
    cRef ! msg3
    aRef ! msg4

Actor C在消息处理程序中执行以下代码:

case msg3 => 
    aRef ! msg5

我可以做出以下假设(如果有的话):

  1. 演员B在获得msg2之前得到msg1

  2. 演员A获得msg5之前获得msg4

  3. 可能导致理解上述内容的后续问题: 是由!发送的消息!运营商是通过网络真正异步还是等到接收邮箱获得它? 即行

    bRef ! msg1
    

    阻止,直到演员B在其邮箱中获取消息或者它是否产生处理传递并继续执行的线程

    bRef ! msg2
    

    之前它甚至知道演员B得到了msg1?

2 个答案:

答案 0 :(得分:8)

对于(1),您可以保证msg1将在msg2之前由调度员排队。一旦他们入队,实际发生的事情实际上取决于您使用的调度员:http://akka.io/docs/akka/1.1.2/scala/dispatchers.html,但在您的情况下,只要B可以接受这两个消息,那么它将始终在msg2之前接收msg1。

对于(2),不,你没有这个保证。的!一旦调度程序将消息排入队列,方法就会返回,而不是当目标actor的邮箱接受该消息时。然后发送在另一个线程中完成,并受到各种竞争条件的影响。

  

是否发送了消息!运营商是通过网络真正异步还是等到接收邮箱得到它?

您可以将BoundedMailbox与本地actor一起使用,以显示向调度程序排队的消息是异步的!:

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

打印:

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

scala> Received message
Received message

这意味着在您甚至知道是否将传递消息之前,主线程中的代码执行仍在继续。在这种情况下,如果我们在调度程序上设置了pushTimeout并使Thread.sleep等待超过超时,则消息发送很容易超时。

将此与使用!!:

进行比较
scala>     t !! "one"; t !! "two"; t !! "three"; println("test");
Received message
Received message
Received message
test

所以,考虑到这一点。实现(2)的方法是:

case msg1 =>
  cRef !! msg3
  aRef ! msg4 

答案 1 :(得分:1)

Erlang为您提供第一个保证,但不是第二个保证。 Akka可能会给你第一个保证,但肯定不会给你第二个保证。

我不知道你的后续问题的答案。