Akka终止未发送或路由到其他地方的消息
我有几个演员,每个演员都有多个路由器,用于特定类型的演员。我创建了一个类RouteeTracker(你猜对了)来跟踪每种类型的路由器所属的角色。这是为了正确处理来自每种类型的参与者的终止消息Akka终止未发送或路由到其他地方的消息,akka,router,actor,terminate,Akka,Router,Actor,Terminate,我有几个演员,每个演员都有多个路由器,用于特定类型的演员。我创建了一个类RouteeTracker(你猜对了)来跟踪每种类型的路由器所属的角色。这是为了正确处理来自每种类型的参与者的终止消息 public class RouteeTracker { private static final Logger logger = LoggerFactory.getLogger(RouteeTracker.class); private Map<ActorRef, Router&g
public class RouteeTracker
{
private static final Logger logger = LoggerFactory.getLogger(RouteeTracker.class);
private Map<ActorRef, Router> routeeRouterMap = new HashMap<ActorRef, Router>();
private Map<ActorRef, Class> routeeClassMap = new HashMap<ActorRef, Class>();
private Map<Class, String> routeeDispatcherMap = new HashMap<Class, String>();
Router register(Class actorClass, int actorPoolCount, UntypedActorContext untypedActorContext, RoutingLogic routingLogic, ApplicationContext applicationContext, String dispatcher)
{
List<Routee> routees;
List<ActorRef> actors;
routees = new ArrayList<>();
actors = new ArrayList<>();
for (int i = 0; i < actorPoolCount; i++) {
ActorRef r = untypedActorContext.actorOf(Props.create(actorClass, applicationContext).withDispatcher(dispatcher));
logger.info("r={}",r.toString());
actors.add(r);
**untypedActorContext.watch(r);**
routees.add(new ActorRefRoutee(r));
}
**Router router = new Router(routingLogic, routees);**
routeeDispatcherMap.put(actorClass, dispatcher);
for(ActorRef actor:actors)
{
routeeRouterMap.put(actor, router);
routeeClassMap.put(actor, actorClass);
}
return router;
}
ActorRef handleTerminate(ActorRef actorRef, UntypedActorContext untypedActorContext)
{
logger.info("Entering RouteeTracker.handleTerminate({,{})",actorRef.toString(), untypedActorContext.toString());
Router router = routeeRouterMap.get(actorRef);
if(router == null)
throw new RuntimeException("No router found for actorRef");
Class actorClass = routeeClassMap.get(actorRef);
String dispatcher = routeeDispatcherMap.get(actorClass);
if(actorClass == null)
throw new RuntimeException("No actorClass found for actorRef");
**strong text**router.removeRoutee(actorRef);
logger.info("####class:dispatcher {}:{}",actorClass.toString(),dispatcher);
ActorRef r = untypedActorContext.actorOf(Props.create(actorClass).withDispatcher(dispatcher));
untypedActorContext.watch(r);
router.addRoutee(new ActorRefRoutee(r));
//Cleanup
routeeRouterMap.remove(actorRef);
routeeClassMap.remove(actorRef);
logger.info("Exiting RouteeTracker.handleTerminate({,{})",actorRef.toString(), untypedActorContext.toString());
return r;
}
}
公共类路由跟踪器
{
私有静态最终记录器Logger=LoggerFactory.getLogger(RouteeTracker.class);
私有映射routeeRouterMap=newHashMap();
私有映射routeeClassMap=newHashMap();
私有映射RouteDispatcherMap=newHashMap();
路由器寄存器(类actorClass、int actorPoolCount、UntypedActorContext UntypedActorContext、路由逻辑路由逻辑、应用上下文应用上下文、字符串分派器)
{
列出路线;
列出行动者名单;
routees=新的ArrayList();
actors=newarraylist();
for(int i=0;i
我在这样一个演员身上使用这个路由器:
public class Supervisor extends UntypedActor {
private static final Logger logger = LoggerFactory.getLogger(Supervisor.class);
public static Props props(final ApplicationContext applicationContext) {
return Props.create(new Creator<Supervisor>() {
private static final long serialVersionUID = 1L;
@Override
public Supervisor create() throws Exception {
return new Supervisor(applicationContext);
}
});
}
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() { return applicationContext; }
public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; }
private Router SIPRRouter;
private Router SICRouter;
private Router VFERouter;
private RouteeTracker routeeTracker = new RouteeTracker();
public Supervisor(ApplicationContext applicationContext)
{
this.applicationContext = applicationContext;
sessionIdentifierGenerator = (SessionIdentifierGeneratorService) this.applicationContext.getBean("sessionIdentifierGeneratorServiceImpl");
}
@Override
public void preStart() throws Exception {
SIPRouter = routeeTracker.register(SIEProducer.class, 5, **getContext()**, new RoundRobinRoutingLogic(), applicationContext, "si-bio-d");
SICRouter = routeeTracker.register(SIEConsumer.class, 5, **getContext()**, new RoundRobinRoutingLogic(), applicationContext, "si-bio-d");
vfeRouter = routeeTracker.register(VFE.class, 10, **getContext()**, new RoundRobinRoutingLogic(), applicationContext, "fe-bio-d");
}
@Override
public void onReceive(Object message) throws Exception {
if (message instanceof String) {
String msg = (String) message;
logger.debug("Supervisor::Received String message: {}", msg);
} else if(message instanceof Terminated) {
logger.info("handle terminated");
routeeTracker.handleTerminate(((Terminated) message).actor(),getContext());
} else {
unhandled(message);
}
message = null;
}
}
公共类主管扩展了UntypedActor{
专用静态最终记录器记录器=LoggerFactory.getLogger(Supervisor.class);
公共静态道具道具(最终应用程序上下文应用程序上下文){
返回道具。创建(新创建者(){
私有静态最终长serialVersionUID=1L;
@凌驾
公共主管create()引发异常{
返回新主管(applicationContext);
}
});
}
私有应用程序上下文应用程序上下文;
公共应用程序上下文getApplicationContext(){return ApplicationContext;}
public void setApplicationContext(ApplicationContext ApplicationContext){this.ApplicationContext=ApplicationContext;}
专用路由器;
专用路由器;
专用路由器VFERouter;
专用RouteeTracker RouteeTracker=新RouteeTracker();
公共主管(应用上下文应用上下文)
{
this.applicationContext=applicationContext;
sessionIdentifierGenerator=(SessionIdentifierGeneratorService)this.applicationContext.getBean(“sessionIdentifierGeneratorServiceImpl”);
}
@凌驾
public void preStart()引发异常{
SIPRouter=routeeTracker.register(SIEProducer.class,5,**getContext()**,新RoundRobinRoutingLogic(),applicationContext,“si-bio-d”);
SICRouter=routeeTracker.register(SIEConsumer.class,5,**getContext()**,新RoundRobinRoutingLogic(),applicationContext,“si-bio-d”);
vfeRouter=routeeTracker.register(VFE.class,10,**getContext()**,新RoundRobinRoutingLogic(),applicationContext,“fe-bio-d”);
}
@凌驾
public void onReceive(对象消息)引发异常{
if(字符串的消息实例){
字符串消息=(字符串)消息;
debug(“Supervisor::Received String message:{}”,msg);
}else if(消息instanceof Terminated){
logger.info(“句柄终止”);
routeeTracker.handleTerminate(((终止)message.actor(),getContext());
}否则{
未处理(消息);
}
消息=null;
}
}
为了清晰起见,我删除了许多与处理终止消息无关的消息。问题是参与者从未收到终止消息。因此,我的RouteeTracker.HandleteTerminated()方法从未被调用。我只能假设消息从未被发送,可能是因为这些子参与者没有终止,或者终止消息没有被发送
我的路由器使用基于Typesafe官方Akka Java文档
我调用untypedActor.watch(…),并在routeeTracker的register方法中添加新创建的actor
我在routeeTracker的terminate方法中将actor从路由器(和其他数据结构)中移除
儿童演员似乎没有被监视
有人想吗?答案是42。答案是42。