15

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

假设我们有远程参与者分布在 3 台机器(A、B、C)的集群中,其中每台机器上都有一个参与者,而其他参与者则拥有另外 2 台参与者的 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)

演员 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 在得到 msg4 之前得到 msg5

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

bRef ! msg1

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

bRef ! msg2

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

4

2 回答 2

9

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

对于 (2),不,您没有此保证。这 !方法在调度程序将消息排入队列时立即返回,而不是在目标参与者的邮箱接受消息时返回。然后在另一个线程中完成发送,并受制于各种竞争条件。

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

您可以将 BoundedMailbox 与本地参与者一起使用,以表明将消息排入调度程序与 ! 是异步的:

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 
于 2011-06-01T14:36:48.143 回答
1

Erlang 给了你第一个保证,但不是第二个。Akka 可能也会给你第一个保证,但它肯定不会给你第二个保证。

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

于 2011-06-01T14:19:43.300 回答