0

我一直在研究 Akka Actor 模型。我有一个用例,其中将有 1000 多个演员处于活动状态,我必须处理这些演员。我想过通过application.conf中定义的配置来控制线程数。

但不是。在我的应用程序中创建的调度程序线程使我无法调整调度程序配置。每次重新启动我的应用程序时,我都会看到创建了不同数量的调度程序线程(我每次启动应用程序后都通过线程转储检查了这一点)。

甚至线程数也不等于我在 parallelism-min 中定义的线程数。由于线程数很少,我的应用程序处理速度非常慢。在检查没有。通过以下代码在我的机器中获取核心:

Runtime.getRuntime().availableProcessors();

它显示 40。但没有。即使我将并行度配置为 500,创建的调度程序线程数也少于 300。

以下是我的 application.conf 文件:

consumer-dispatcher {
  type = "Dispatcher"

  executor = "fork-join-executor"

  fork-join-executor {
    parallelism-min = 500
    parallelism-factor = 20.0
    parallelism-max = 1000
  }

  shutdown-timeout = 1s

  throughput = 1
}

我可以知道 akka 将在什么基础上在内部创建调度程序线程以及如何增加调度程序线程数以增加参与者的并行处理?

4

1 回答 1

1

来自讨论.lightbend.com的 X-Post

首先让我直接回答这个问题。

Afork-join-executor将由一个java.util.concurrent.forkJoinPool池支持,其并行度设置为调度程序配置中的隐含并行度。(并行因子 * 处理器,但不大于最大值或小于最小值)。所以,在你的情况下,800。

虽然我不是ForkJoinPoolJava 实现源代码的实现专家,但它ForkJoinPool说“所有工作线程的创建都是按需创建的,由任务提交、终止工作人员的替换和/或对阻塞工作人员的补偿触发。” 并且它有类似的方法getActiveThreads(),所以很明显,ForkJoinPool它不仅仅天真地创建了一个巨大的工人池。

换句话说,您所看到的是预期的:它只会在需要时创建线程。如果你真的必须有一个巨大的工作线程池,你可以创建一个固定池大小为 800 的线程池执行器。这将为你提供你正在寻找的实现。

但是,在你这样做之前,我认为你完全忽略了演员和 Akka 的意义。人们喜欢 Actor 的原因之一是它们比线程轻得多,并且可以为您提供比线程更多的并发性。(另请注意,concurrency != 并行性,如有关概念的文档中所述。)因此,尝试创建一个包含 800 个线程的池来支持 1000 个参与者是非常浪费的。在akka 文档介绍 中,它强调了“数以百万计的参与者可以有效地安排在十几个线程上”。

在不知道您的应用程序(例如,如果您有阻塞行为)的情况下,我无法准确告诉您需要多少线程,但默认值(这将使您的并行度因子为 20)可能就可以了。可以确定基准,但我真的不认为你有线程太少的问题。(ForkJoinPool您观察到的行为似乎证实了这一点。)

于 2020-03-21T03:03:50.660 回答