22

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

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

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

4

4 回答 4

23

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

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

于 2012-03-06T14:57:30.650 回答
0

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

例如,平衡池路由器允许您让一组特定类型的固定参与者共享同一个邮箱:

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

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

于 2015-05-19T16:19:12.323 回答
0

我正在分析(visualvm)来自 AKKA 文档的示例集群应用程序之一,我看到垃圾收集在每次 GC 期间清理了每个请求参与者。无法完全理解使用后明确杀死actor的建议。我的actorsystem 和actors 由SPRING IOC 容器管理,我使用spring 扩展间接actor-producer 来创建actors。“聚合器”参与者正在每次 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();
    }
}
于 2018-01-20T05:25:28.030 回答
-3

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

于 2012-03-06T01:25:46.147 回答