Akka中Sender引用出现Dead Letters问题及解决方案咨询
问题原因分析
你碰到这个问题的核心是错误地在Actor类的初始化阶段就获取了sender()引用。在Akka中,sender()的返回值是和当前正在处理的消息绑定的——只有在receive方法(或其他消息处理逻辑的上下文里),它才会指向发送当前消息的Actor实例。而当Actor刚被创建、还没处理任何消息时,sender()默认指向Dead Letters,这就是你看到异常输出的原因。
修正后的代码
把获取sender引用的逻辑移到receive方法内部,确保在消息处理的有效上下文里获取引用:
object SenderTest extends App { val s = ActorSystem("test") val ar = s.actorOf(Props[A], "Aactor") ar ! "abc" } class A extends Actor { // 移除类初始化阶段的sender_变量,此时无消息上下文,引用无效 override def receive: Receive = { case _: String => { println("inside A receive block") val b = context.actorOf(Props[B], "Bactor") b ! 12 } } } class B extends Actor { override def receive: Receive = { case _: Int => { // 在消息处理时获取sender,此时上下文绑定的是发送当前消息的Actor A val sender_ = sender() println(sender_) println("inside B receive block") sender_ ! 22 } } }
额外注意事项
如果你的Actor需要在异步操作(比如Future调用)完成后回复消息,一定要在receive方法里先捕获当前的sender引用,再在闭包中使用——不能直接在异步逻辑里调用sender(),因为此时的消息上下文已经切换,sender()会指向错误的对象:
class B extends Actor { import context.dispatcher override def receive: Receive = { case _: Int => { // 先捕获当前消息的sender引用 val currentSender = sender() println(currentSender) println("inside B receive block") // 异步操作中使用捕获的引用 Future { // 这里不能直接用sender(),必须用currentSender currentSender ! 22 } } } }
内容的提问来源于stack exchange,提问作者Aamir
相关产品推荐
相关产品推荐

