我编写了以下代码:
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
?
这未连接到无效字母,请参阅消息传递可靠性。在Akka中,使用In-JVM消息传递时-您可以确保在大多数情况下以高概率传递消息(在异常之后重启是其中之一)。无法发送的消息(例如,向自愿停止或从未存在的演员发送的消息)将进入DeadLetters框,但是您应该明确地订阅它们,这不是您想要的。您刚刚从您自己的actor的邮箱中收到了消息(因为重新启动过程中未删除该框-仅是actor的实例)。您需要显式订阅相应的事件流才能观看deadLetter。
您无法处理context.stop(self)
内部supervisorStrategy
事务,因为它是自愿终止(实际上会导致消息发送到DeadLetters),而不是特殊情况(失败)。所以1/0
和context.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] 删除。
我来说两句