【问题标题】:Message delivery sequence in akka actorsakka actor 中的消息传递序列
【发布时间】:2011-09-06 07:08:30
【问题描述】:

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

假设我们有远程 Actor 分布在 3 台机器(A、B、C)的集群中,其中每台机器上都有一个 Actor,其他的 ActorRef 指向另外 2 台机器,即:

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 在获得 msg4 之前获得 msg5

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

bRef ! msg1

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

bRef ! msg2

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

【问题讨论】:

    标签: scala messages actor akka mq


    【解决方案1】:

    对于 (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 
    

    【讨论】:

    • 您实际上并没有解决 1. 和 2.,尽管您可以推断 2. 从您所展示的内容中不成立。然而,这并没有解决 1. 的问题。
    • 你是对的。我修改了我的答案以回答我正在回答的具体问题。
    • 你确定要实现(2)我也不必将actor C代码更改为aRef!味精5?
    • 你能解释一下!! 做了什么,或者链接到关于它的 Akka 文档页面吗?显然它在等待,例如 ?,但我在 Google 或 Akka 资源中找不到任何关于它的信息。
    • @chbrown 搞清楚!!
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-06
      • 1970-01-01
      • 2021-06-19
      • 2014-05-13
      • 2012-09-02
      • 2015-02-13
      • 2015-08-05
      • 1970-01-01
      相关资源
      最近更新 更多