Java 如何检测akka actor因系统关闭而终止,并避免重新启动
我有一个Spring应用程序,它利用了一个小的Akka actor系统(使用Java),其中我有一个Java 如何检测akka actor因系统关闭而终止,并避免重新启动,java,akka,akka-actor,Java,Akka,Akka Actor,我有一个Spring应用程序,它利用了一个小的Akka actor系统(使用Java),其中我有一个MasterActor,它扩展了Akka的AbstractActor,初始化了一个路由器,并设置了几个工作角色。它还监视工人的生命周期。我想重新启动一个Worker-actor,如果它因为一些异常而死亡 public MasterActor(ActorPropsFactory actorPropsFactory) { this.actorPropsFactory = actorProps
MasterActor
,它扩展了Akka的AbstractActor
,初始化了一个路由器
,并设置了几个工作角色。它还监视工人的生命周期。我想重新启动一个Worker-actor,如果它因为一些异常而死亡
public MasterActor(ActorPropsFactory actorPropsFactory) {
this.actorPropsFactory = actorPropsFactory;
int workers = Runtime.getRuntime().availableProcessors() - 1;
List<Routee> routees = Stream.generate(this::createActorRefRoutee).limit(workers).collect(Collectors.toList());
this.router = new Router(new ConsistentHashingRoutingLogic(getContext().system()), routees);
}
private ActorRefRoutee createActorRefRoutee() {
ActorRef worker = getContext().actorOf(actorPropsFactory.create(getWorkerActorClass()));
getContext().watch(worker);
return new ActorRefRoutee(worker);
}
private void route(Object message, Supplier<String> routingKeySupplier) {
String routingKey = routingKeySupplier.get();
RouterEnvelope envelope = new ConsistentHashingRouter.ConsistentHashableEnvelope(message, routingKey);
router.route(envelope, getSender());
}
@Override
public Receive createReceive() {
return receiveBuilder()
.match(
EventMessage.class,
message -> this.route(message, () -> message.getEvent().getId().toString()))
.match(
Terminated.class,
message -> {
logger.info("WorkerActor {} terminated, restarting", message.getActor());
// todo: detect whether the system is shutting down before restarting the actor
router = router.removeRoutee(message.actor())
.addRoutee(createActorRefRoutee());
})
.build();
}
public MasterActor(ActorPropsFactory ActorPropsFactory){
this.actorPropsFactory=actorPropsFactory;
int workers=Runtime.getRuntime().availableProcessors()-1;
List routees=Stream.generate(this::createActorRefRoutee).limit(workers).collect(Collectors.toList());
this.router=新路由器(新的一致HashingRoutingLogic(getContext().system()),路由对象);
}
私有ActorRefRoutee createActorRefRoutee(){
ActorRef worker=getContext().actorOf(actorPropsFactory.create(getWorkerActorClass());
getContext().watch(worker);
返回新的ActorRefRoutee(工人);
}
专用无效路由(对象消息、供应商路由密钥供应商){
String routingKey=routingKeySupplier.get();
RouterEnvelope=新的ConsistentHashingRouter.ConsistentHashingEnvelope(消息、路由密钥);
route(信封,getSender());
}
@凌驾
公共接收createReceive(){
return receiveBuilder()
.比赛(
EventMessage.class,
message->this.route(message,()->message.getEvent().getId().toString())
.比赛(
第二节课,
信息->{
info(“WorkerActor{}终止,重新启动”,message.getActor());
//todo:在重新启动actor之前检测系统是否正在关闭
路由器=路由器.removeRoutee(message.actor())
.addRoutee(createActorRefRoutee());
})
.build();
}
我遇到的问题是,如果Spring应用程序无法启动。(例如,它无法连接到数据库,或者某些凭据不正确等等),我收到来自所有工作人员的终止
消息,主参与者尝试启动新的工作人员,这些工作人员也会立即被终止
,进入一个无休止的循环
检测这种情况的正确方法是什么?有没有办法让主参与者检测到参与者系统正在关闭,这样工人就不会再次重新启动?您不能为路由器设置一个监控策略,以便检查导致故障的异常类型吗?这样,您也不需要手动重新启动工作程序 编辑: 您可以这样设置
SupervisorStrategy
:
private static SupervisorStrategy strategy=
new OneForOneStrategy(
10,
Duration.ofMinutes(1),
DeciderBuilder.match(ArithmeticException.class,e->SupervisorStrategy.resume())
.match(NullPointerException.class,e->SupervisorStrategy.restart())
.match(IllegalArgumentException.class,e->SupervisorStrategy.stop())
.matchAny(o->SupervisorStrategy.escalate())
.build());
final ActorRef router=
system.actorOf(
new RoundRobinPool(5).withSupervisorStrategy(strategy).props(Props.create(Echo.class)));
您可以在此处阅读更多信息:
您不能为路由器设置一个监控策略,以便检查导致故障的异常类型吗?这样,您也不需要手动重新启动工作程序 编辑: 您可以这样设置
SupervisorStrategy
:
private static SupervisorStrategy strategy=
new OneForOneStrategy(
10,
Duration.ofMinutes(1),
DeciderBuilder.match(ArithmeticException.class,e->SupervisorStrategy.resume())
.match(NullPointerException.class,e->SupervisorStrategy.restart())
.match(IllegalArgumentException.class,e->SupervisorStrategy.stop())
.matchAny(o->SupervisorStrategy.escalate())
.build());
final ActorRef router=
system.actorOf(
new RoundRobinPool(5).withSupervisorStrategy(strategy).props(Props.create(Echo.class)));
您可以在此处阅读更多信息:
当你检测到启动失败时,难道你不能发送一条消息给master actor吗?@plalx很难检测到启动失败。依赖项可能会由于许多原因而失败,而使用像Spring这样的依赖项注入框架的全部目的是从解析和加载依赖项的锅炉板中抽象出来。我可以用一个关机钩子绕过它,但我真的很想了解到底是什么首先向我的工作人员发送终止消息,以及是否有一些状态信息可以告诉我为什么要终止actor,以确定重新启动它是否有意义。当检测到启动失败时,你不能只向master actor发送消息吗?@plalx检测启动失败并不容易。依赖项可能会由于许多原因而失败,而使用像Spring这样的依赖项注入框架的全部目的是从解析和加载依赖项的锅炉板中抽象出来。我可以用一个关机钩子来破解它,但我真的很想了解到底是什么首先向我的工作人员发送终止消息,以及是否有一些状态信息可以告诉我为什么演员被终止,以确定重新启动它是否有意义。你怎么做?(对不起,我对Akka比较陌生)@jbx编辑了来自Akka文档的示例,并链接到关于路由器中的监管策略和监管的文章。我希望这会有帮助。你是怎么做到的?(对不起,我对Akka比较陌生)@jbx编辑了来自Akka文档的示例,并链接到关于路由器中的监管策略和监管的文章。我希望这会有帮助。