akka演员中的消息传递顺序

Gro*_*ozz 15 scala messages mq actor akka

我是Akka的新手,在参考手册中找不到答案.

假设我们有远程actor分布在3台机器(A,B,C)的集群中,其中一个actor存在于每台机器上,而其他actor则有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)
Run Code Online (Sandbox Code Playgroud)

Actor A执行以下代码:

bRef ! msg1
bRef ! msg2
Run Code Online (Sandbox Code Playgroud)

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

case msg1 => 
    cRef ! msg3
    aRef ! msg4
Run Code Online (Sandbox Code Playgroud)

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

case msg3 => 
    aRef ! msg5
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

bRef ! msg1
Run Code Online (Sandbox Code Playgroud)

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

bRef ! msg2
Run Code Online (Sandbox Code Playgroud)

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

Dav*_*lin 9

对于(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");
Run Code Online (Sandbox Code Playgroud)

打印:

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

scala> Received message
Received message
Run Code Online (Sandbox Code Playgroud)

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

将此与使用!!进行比较:

scala>     t !! "one"; t !! "two"; t !! "three"; println("test");
Received message
Received message
Received message
test
Run Code Online (Sandbox Code Playgroud)

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

case msg1 =>
  cRef !! msg3
  aRef ! msg4 
Run Code Online (Sandbox Code Playgroud)