DeadLetters和ActorRef出错

时间:2014-09-02 06:46:30

标签: scala akka

我在运行项目时遇到错误,我无法解决。

这是我的代码:

import akka.actor._
import akka.actor.Actor
import akka.actor.ActorSystem
import akka.actor.Props
import akka.actor.ScalaActorRef
import akka.pattern.gracefulStop
import akka.util._
import java.util.Calendar
import java.util.concurrent._
import java.text.SimpleDateFormat
import scala.Array._
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global

sealed trait Message
case class ReturnInfluenceMessage(source: ActorRef) extends Message
case class SetInfluences(source: ActorRef) extends Message
case class GetInfluence() extends Message

class Listener extends Actor {
    def receive = {
        case ReturnInfluenceMessage(s0urce) => println ("Listener: received influence (" +     s0urce + ")")
    }
}

class Entity extends Actor {
    val Influences = context.actorOf(Props[Influences], name = "Influences")
    def receive = {
        case SetInfluences(s0urce) => context.children foreach     (_.forward(SetInfluences(s0urce)))
        case GetInfluence => context.children foreach (_.forward(GetInfluence))
        case ReturnInfluenceMessage(source) =>
            source ! ReturnInfluenceMessage(source)
    }
}

class Influences extends Actor {
    private var source: ActorRef = _
    def receive = {
        case SetInfluences(s0urce)  => 
            source = s0urce
            println ("Influences: received " + s0urce)
            println ("Influences: Influence set to " + source)
        case GetInfluence =>
            println ("Influences: influence sent to " + source)
            sender ! ReturnInfluenceMessage(source)
    }
}

object main extends App {
    val system = akka.actor.ActorSystem("mySystem")
    val Abel = system.actorOf(Props[Listener], name = "Listener")
    val Cain = system.actorOf(Props[Entity], name = "Entity")

    system.scheduler.scheduleOnce(1500 milliseconds, Cain, SetInfluences(Abel))
    system.scheduler.scheduleOnce(3000 milliseconds, Cain, GetInfluence)
}

这里的错误:

 [INFO] [08/29/2014 15:39:08.330] [mySystem-akka.actor.default-dispatcher-2] [akka://mySystem
 /deadLetters] Message [ReturnInfluenceMessage] from Actor[akka://mySystem/user/Entity
 /Shadow/Influences#1407138271] to Actor[akka://mySystem/deadLetters] 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'.

我正在尝试设置source actor的变量Cain,让最后一个发送ActorRef Abel source消息,其中source ! ReturnInfluenceMessage(source) 变量并显示它。 错误发生在这里:

{{1}}

,我不知道为什么会这样。

2 个答案:

答案 0 :(得分:2)

@Martynas是正确的,因为当您的代码按原样设置时,sender引用将成为DeadLetter引用。主要问题是您从演员系统外部发送消息(通过调度程序),然后当您使用forward时,您继续传播您没有发送者的事实下一个演员。您可以使用tell (!)代替转发来解决此问题。我已修改您的代码示例以显示此代码(以及代码示例后描述的其他一些更改):

import akka.actor._
import concurrent.duration._

sealed trait Message
case class ReturnInfluenceMessage(source: ActorRef) extends Message
case class SetInfluences(source: ActorRef) extends Message
case object GetInfluence extends Message

class Listener extends Actor {
  def receive = {
    case ReturnInfluenceMessage(s0urce) => println(s"Listener: received influence ($s0urce)")
  }
}

class Entity extends Actor {
  val influences = context.actorOf(Props[Influences], name = "Influences")
  def receive = {
    case si @ SetInfluences(s0urce) => 
      influences ! si

    case GetInfluence => 
      influences ! GetInfluence

    case rim @ ReturnInfluenceMessage(source) =>
      source ! rim
  }
}

class Influences extends Actor {
  def receive = setInfluence

  def setInfluence:Receive = {
    case SetInfluences(s0urce)  => 
      println (s"Influences: received $s0urce")
      println (s"Influences: Influence set to $s0urce")    
      context.become(withSource(s0urce) orElse setInfluence)
  }

  def withSource(source:ActorRef):Receive = {
    case GetInfluence =>
      println (s"Influences: influence sent to $source")
      sender ! ReturnInfluenceMessage(source)      
  }    
}

object Main extends App {
  val system = akka.actor.ActorSystem("mySystem")
  val abel = system.actorOf(Props[Listener], name = "Listener")
  val cain = system.actorOf(Props[Entity], name = "Entity")

  import system.dispatcher
  system.scheduler.scheduleOnce(1500 milliseconds, cain, SetInfluences(abel))
  system.scheduler.scheduleOnce(3000 milliseconds, cain, GetInfluence)
}

当我跑步时,我没有得到任何动物。其他变化包括:

  • 格式化(缩进2个空格,var / vals的正确大小)
  • GetInfluence更改为案例对象,因为它没有任何字段
  • 在case语句中使用变量绑定来捕获对消息的引用(通过@符号)当我们需要发送该消息时
  • Influences actor使用两个状态设置,它首先等待设置状态(source ref),然后切换到能够正确响应的状态一条GetInfluences消息。可能希望在初始状态下显式处理GetInfluences消息,因为现在它只是一条未处理的消息。
  • 摆脱children.foreach的使用,因为你已经有一个对该actor唯一的孩子的引用,所以似乎没有必要使用这个构造。如果你有不同数量的孩子要发送给​​我,我会使用那个结构,在这个例子中你不会。

答案 1 :(得分:1)

使用

安排留言时
system.scheduler.scheduleOnce(...)

该邮件的发件人是DeadLetters,这是您尝试向

发送邮件的内容
sender ! ReturnInfluenceMessage(source)

它也是错误信息所说的。