死信箱可以在Akka中重用吗?

斯康尼

我编写了以下代码:

package com.star.wars

import akka.actor._
import akka.actor.SupervisorStrategy._
import akka.util.duration._

object Test extends App {

  case object Kill
  case object Create

  class Luke extends Actor {

    var x: Int = 0

    println("Luke here")
    Thread.sleep(1000)
    println("Luke here2")

    def receive = {
      case Kill => 1/0// context.stop(self)
      case msg: String => {
        x += 1
        println(x + msg)
      }
    }

  }

  class Vader extends Actor {

    println("Vader here")

    override val supervisorStrategy =
      OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
        case _: ArithmeticException      => Restart
        case _: NullPointerException     => Restart
        case _: IllegalArgumentException => Restart
        case _: Exception                => Restart
      }

    def receive = {
      case Create => context.actorOf(Props(new Luke), name = "Luke")
      case Kill => {
        val luke = context.actorFor("/user/Vader/Luke")
        luke ! "Pre hi there"
        luke ! Kill
        luke ! "Post hi there"
        println("Pre -> Kill -> Post sent to Luke")
      }
    }

  }

  val system = ActorSystem("MySystem")
  val vader = system.actorOf(Props(new Vader), name = "Vader")
  vader ! Create
  vader ! Kill
  println("Create -> Kill sent to Vader")

}

这段代码的目的是证明,在卢克重新启动时,他的死信箱可以接收消息,而当卢克再次联机时,他可以在他不在时接收发送给他的消息。

输出似乎还可以。这是一种证明:

Create -> Kill sent to Vader
Vader here
Luke here
Pre -> Kill -> Post sent to Luke
Luke here2
1Pre hi there
[ERROR] [01/12/2015 00:32:02.74] [MySystem-akka.actor.default-dispatcher-3] [akka://MySystem/user/Vader/Luke] / by zero
java.lang.ArithmeticException: / by zero
    at com.sconysoft.robocode.Test$Luke$$anonfun$receive$1.apply(test.scala:21)
    at com.sconysoft.robocode.Test$Luke$$anonfun$receive$1.apply(test.scala:20)
    at akka.actor.Actor$class.apply(Actor.scala:318)
    at com.sconysoft.robocode.Test$Luke.apply(test.scala:12)
    at akka.actor.ActorCell.invoke(ActorCell.scala:626)
    at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:197)
    at akka.dispatch.Mailbox.run(Mailbox.scala:179)
    at akka.dispatch.ForkJoinExecutorConfigurator$MailboxExecutionTask.exec(AbstractDispatcher.scala:516)
    at akka.jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:259)
    at akka.jsr166y.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:975)
    at akka.jsr166y.ForkJoinPool.runWorker(ForkJoinPool.java:1479)
    at akka.jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:104)

Luke here
Luke here2
1Post hi there

但是,我不确定这是否总是真理。我在akka文档中找不到它,所以我的推理还可以吗?死信箱是否可以在Akka中重新使用(在actor重新启动之后)?

顺便提一句。我如何处理context.stop(self)维达的卢克(Luke supervisorStrategy

dk14

这未连接到无效字母,请参阅消息传递可靠性在Akka中,使用In-JVM消息传递时-您可以确保在大多数情况下以高概率传递消息(在异常之后重启是其中之一)。无法发送的消息(例如,向自愿停止或从未存在的演员发送的消息)将进入DeadLetters框,但是您应该明确地订阅它们,这不是您想要的。您刚刚从您自己的actor的邮箱中收到了消息(因为重新启动过程中未删除该框-仅是actor的实例)。您需要显式订阅相应的事件流才能观看deadLetter。

您无法处理context.stop(self)内部supervisorStrategy事务,因为它是自愿终止(实际上会导致消息发送到DeadLetters),而不是特殊情况(失败)。所以1/0context.stop(self)有很大的不同。有关倾听儿童生命周期的信息,请参阅-生命周期监控的含义

例如,让我们看看如果您真正context.stop(self)输入代码而不是1/0

Luke here
Pre -> Kill -> Post sent to Luke
Luke here2
1Pre hi there
[INFO] [01/12/2015 09:20:37.325] [MySystem-akka.actor.default-dispatcher-4] [akka://MySystem/user/Vader/Luke] Message [java.lang.String] from Actor[akka://MySystem/user/Vader#-1749418461] to Actor[akka://MySystem/user/Vader/Luke#-1436540331] was not delivered. [1] dead letters encountered. This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

这就是使用deadLetters邮箱的地方(日志中“ blabla未送达”)。

无论如何,任何交付(包括死信,因为它只是一个合成参与者)都是基于尽力而为原则的,用于JVM中的消息传递,因此没有绝对的保证:

Akka测试套件依赖于在本地上下文中不丢失消息(对于非错误条件测试也适用于远程部署),这意味着我们实际上尽了最大的努力来保持测试的稳定性。但是,与在JVM上进行常规方法调用的原因相同,本地Tell操作可能会失败:

  • StackOverflowError
  • OutOfMemoryError
  • 其他VirtualMachineError

此外,本地发送可能以Akka特定的方式失败:

  • 如果邮箱不接受该消息(例如完整的BoundedMailbox)
  • 如果接收方在处理消息时失败,或者已经终止

虽然第一个显然是有关配置的问题,但是第二个值得考虑:如果处理过程中发生异常,则消息的发送者不会获得反馈,而是将通知发送给主管。通常,这与外部观察者丢失的消息没有区别。

如果进行网络消息传递,则根本无法保证交付。卢克永远不知道谁是他的父亲。为什么?因为它更快,而且实际上没有人需要可靠的消息传递

发送者知道交互是否成功的唯一有意义的方式是通过接收业务级别的确认消息,这不是Akka自己可以弥补的(我们既不是编写“按我的意思做”的框架,也不是您希望我们这样做)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

您可以在Java嵌入式代理中以编程方式更改队列的“死信”处理吗?

来自分类Dev

在CDECL调用约定中,可以重用推入堆栈的参数吗?

来自分类Dev

您可以在GraphViz中建立可重用的样式吗?

来自分类Dev

可以在多个查询中重用CQLinq代码吗?

来自分类Dev

可以在多个查询中重用CQLinq代码吗?

来自分类Dev

Akka测试死信

来自分类Dev

如何查看Akka死信

来自分类Dev

Akka死信与问模式

来自分类Dev

如何查看Akka死信

来自分类Dev

ExecutionContext 导致 Akka 死信

来自分类Dev

回复发件人去死信箱

来自分类Dev

Stringformatter可以重用参数吗?

来自分类Dev

我可以重用ValueAnimator吗?

来自分类Dev

git标签可以重用吗

来自分类Dev

可以重用根分区吗?

来自分类Dev

在Akka中,我可以在实例字段中保存ActorRef吗?

来自分类Dev

在Akka中,我可以在实例字段中保存ActorRef吗?

来自分类Dev

RabbitMQ中的死信死信消息

来自分类Dev

在Akka消息中重用案例声明

来自分类Dev

MVC Razor代码重用-可以重用此代码吗?

来自分类Dev

R中的滞后函数可以不循环地重用R中的计算值吗?

来自分类Dev

JDBI DAO实例可以重用吗?

来自分类Dev

HTML文件可以动态重用吗?

来自分类Dev

注销后可以重用sudo会话吗?

来自分类Dev

Grok学习:信箱中的字母

来自分类Dev

有什么方法可以重用上一页中的表单数据吗?

来自分类Dev

我可以合法地在聚合结构初始化中重用字段吗?

来自分类Dev

我可以重用参数实例从Spark中的聚合函数返回值吗?

来自分类Dev

我可以在以后的itoa()调用中重用相同的缓冲区吗?