Akka:完成后必须清理动态创建的演员吗?

我使用Akka及其Java API UntypedActor实现了一个Actor系统。 在其中,一个actor(类型A)使用getContext().actorOf(...);动态地按需动态启动其他actor(类型B) getContext().actorOf(...); 。 那些B演员会做一些A不再关心的计算。 但我想知道:是否有必要在他们完成后清理那些B型演员? 如果是这样,怎么样?

  • 通过让B actor调用getContext().stop(getSelf())完成后?
  • 通过让B actor调用getSelf().tell(Actors.poisonPill()); 什么时候完成? [这就是我现在正在使用的]。
  • 什么都不做?
  • 通过…?

文档对此并不清楚,或者我忽略了它。 我有一些Scala的基本知识,但Akka的来源并不完全是入门级的东西……

你所描述的是根据“请求”(在A的上下文中定义)创建的单用途参与者,它处理一系列事件然后完成,对吧? 这是绝对正常的,你把它们关闭是正确的:如果你不这样做,它们会随着时间的推移累积而你会遇到内存泄漏。 最好的方法是你提到的第一种可能性(最直接),但第二种也没关系。

一些背景:演员在他们的父母中注册,以便可识别(例如,需要在远程处理,但也在其他地方),并且这种注册使他们不被垃圾收集。 OTOH,每个父母都有权访问它创建的子节点,因此没有自动终止(即通过Akka)是有意义的,而是要求在用户代码中显式关闭。

除了Roland Kuhn的回答之外,您可以创建一组共享同一个调度程序的预定义actor,而不是为每个请求创建一个新的actor,或者您可以使用将请求分发给actor池的路由器。

例如, Balancing Pool Router允许您拥有一组特定类型的固定actor共享同一个邮箱:

 akka.actor.deployment { /parent/router9 { router = balancing-pool nr-of-instances = 5 } } 

阅读有关调度程序和路由的文档以获取更多详细信息。

我正在从AKKA文档中分析(visualvm)样本集群应用程序之一,我看到垃圾收集在每个GC期间清理每个请求actor。 无法完全理解在使用后明确杀死actor的建议。 我的actor系统和actor由SPRING IOC容器管理,我使用spring extension in-direct actor-producer来创​​建actor。 “ 聚合器 ”actor正在每个GC上收集垃圾,我确实监视了可视VM中的实例数。

 @Component @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class StatsService extends AbstractActor { private final LoggingAdapter log = Logging.getLogger(getContext().getSystem(), this); @Autowired private ActorSystem actorSystem; private ActorRef workerRouter; @Override public void preStart() throws Exception { System.out.println("Creating Router" + this.getClass().getCanonicalName()); workerRouter = getContext().actorOf(SPRING_PRO.get(actorSystem) .props("statsWorker").withRouter(new FromConfig()), "workerRouter"); super.preStart(); } @Override public Receive createReceive() { return receiveBuilder() .match(StatsJob.class, job -> !job.getText().isEmpty(), job -> { final String[] words = job.getText().split(" "); final ActorRef replyTo = sender(); final ActorRef aggregator = getContext().actorOf(SPRING_PRO.get(actorSystem) .props("statsAggregator", words.length, replyTo)); for (final String word : words) { workerRouter.tell(new ConsistentHashableEnvelope(word, word), aggregator); } }) .build(); } } 

默认情况下,Actor不会占用太多内存。 如果应用程序打算稍后使用actor b,则可以使它们保持活动状态。 如果没有,你可以通过毒药关闭它们。 只要你的演员没有持有资源,留下一个演员应该没问题。