【问题标题】:Akka: unexpected mailbox filling upAkka:意外的邮箱填满
【发布时间】:2016-10-05 09:23:14
【问题描述】:

我有这个简单的代码:

List<ActorRef> actors = new ArrayList<>();
for (int i = 0; i < ACTOR_COUNT; i++) {
    actors.add(system.actorOf(...));
}
for (ActorRef actor : actors) {
    system.scheduler().schedule(FiniteDuration.create(0, TimeUnit.MILLISECONDS),
            FiniteDuration.create(1000, TimeUnit.MILLISECONDS), actor, "Run", system.dispatcher(), null);
}

它创建了许多参与者,然后为每个参与者创建一个调度程序。 Actors 本身负责查询 MQ,然后处理消息。

当 ACTOR_COUNT > 30 时,一切正常。但除此之外,我们有内存泄漏(带有消息“Run”的 akka.dispatch.Envelopes 实例正在填满,无法进行垃圾回收)

这很奇怪,因为当我们有更多的演员时,我们就会有更多的消息(每个人每秒 1 条) - 但意外的是,当有更多的演员/消息时,它会停止填充。

时间间隔(1000 毫秒)并不会真正影响情况,它只会让它变慢或变快。

您能帮我解释一下这种行为吗?

谢谢。

更新

这是一个虚拟演员,可以帮助隔离问题。

public class MessageQueueTestActor extends UntypedActor {

    private static final Logger log = LoggerFactory.getLogger(MessageQueueTestActor.class);

    @Override
    public void onReceive(Object message) throws Exception {
        Thread.sleep(3000);
    }
}

问题在 ACTOR_COUNT = 5 时重现。现在很明显,当演员睡眠时间 > 调度程序间隔时,信封已填满。如果我将睡眠时间从 3000ms 减少到 500ms,问题就消失了。

但是如果我将参与者的数量增加到 30 个(具有相同的睡眠时间 = 3000 毫秒),垃圾收集器也可以使用消息。为什么?看起来 Akka 中的某些东西在该阈值之后开始以不同的方式工作。

【问题讨论】:

  • 老实说,这听起来确实很奇怪。你可以添加你的演员接收方法的代码吗?你会使用成为/不成为吗?
  • @DiegoMartinoia 我已经更新了帖子,请看一下

标签: java akka


【解决方案1】:

这是一个“调试我的代码”问题,不确定是否应该在这里,但无论如何我都会回答。

调度程序不会将消息排入actor的邮箱本身,它使用给定的调度程序来执行此操作。由于您阻塞了默认调度程序中的线程并使用它来进行排队,因此调度程序中的消息在某个时间点不再到达邮箱(我假设您的默认调度程序有 30 个线程)。更准确地说:他们一个接一个地到达它,而参与者在每个回合中处理最多五个消息。

所以,没有什么是 GC-ed,你只是在不同的地方(默认调度程序)将不同的东西(Runnable)排入队列。如果处理时间长于滴答期,您的程序将永远无法持续运行。

【讨论】:

  • 谢谢。确实,幻数 = 我们的并行系数 * 核心数。现在很清楚了。
猜你喜欢
  • 1970-01-01
  • 2021-06-06
  • 2014-08-14
  • 1970-01-01
  • 1970-01-01
  • 2012-12-17
  • 2014-06-17
  • 2012-04-24
  • 1970-01-01
相关资源
最近更新 更多