Akka Router死信问题求助:消息超5条报错,补Routee仍异常
问题分析与解决办法
嘿,我一眼就揪出问题所在了——你忽略了Akka Router类的不可变性特性!
核心原因
Akka的akka.routing.Router是个不可变对象:当你调用removeRoutee()或者addRoutee()方法时,这些方法不会修改原有的Router实例,而是返回一个包含新路由表的全新Router对象。
看你处理Terminated消息的代码,你只是调用了router.removeRoutee()和router.addRoutee(),但完全没把返回的新Router赋值回原来的router成员变量。这就导致你的Router一直抱着最初那5个已经终止的Routee不放,新创建的Routee根本没被加入到实际路由逻辑里。所以当消息超过5条时,自然会出现死信——因为旧Routee都死透了,新的又没被用上。
解决办法
只需要在更新路由表时,把返回的新Router重新赋值给成员变量就行:
修改Router类中处理Terminated的代码段:
.match(Terminated.class, terminated -> { System.out.println("Got actor terminated message"); // 关键:接收removeRoutee返回的新Router并覆盖原变量 router = router.removeRoutee(new ActorRefRoutee(terminated.actor())); ActorRef actor = getContext().actorOf(Props.create(Actor.class)); getContext().watch(actor); // 同样接收addRoutee返回的新Router router = router.addRoutee(new ActorRefRoutee(actor)); System.out.println("Routee added back"); })
嫌麻烦的话也可以合并成一行更简洁的写法:
router = router.removeRoutee(new ActorRefRoutee(terminated.actor())) .addRoutee(new ActorRefRoutee(getContext().actorOf(Props.create(Actor.class))));
验证效果
修改后再发送超过5条Work消息,每有一个Routee终止,Router就会同步更新自己的路由表,新创建的Routee会被立刻纳入路由逻辑,后续消息就能被正确分发,不会再出现死信问题。
另外提个小建议:把你的Actor类改个名字吧,比如叫WorkerActor,避免和Java内置的类型混淆,可读性会好很多~
内容的提问来源于stack exchange,提问作者bumblebee
相关产品推荐
相关产品推荐

