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

时间:2012-03-05 15:54:44

标签: java akka resource-cleanup

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

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

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

4 个答案:

答案 0 :(得分:23)

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

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

答案 1 :(得分:0)

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

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

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

请阅读dispatchersrouting上的文档以获取更多详细信息。

答案 2 :(得分:0)

我正在从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();
    }
}

答案 3 :(得分:-3)

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