akka 分配给分派程序线程的执行元消息

zpf6vheq  于 2022-11-06  发布在  其他
关注(0)|答案(1)|浏览(162)

众所周知,调度器线程负责执行参与者消息。使用吞吐量参数,我们可以定义在移动到另一个参与者之前由调度器线程处理的消息数
但我不确定调度程序线程将如何选择演员?
比如说,我创建了10,000个参与者,其中只有1000个参与者同时接收消息,其余9000个参与者处于空闲状态,调度程序线程计数为200。
调度程序线程将按什么顺序选取参与者的消息。它是否也将检查空闲参与者邮箱中的消息?
有谁能解释一下调度程序线程选择参与者邮箱消息的流程吗?

wribegjk

wribegjk1#

来自Lightbend论坛的X-Post:https://discuss.lightbend.com/t/actor-message-allocation-to-dispatcher-thread/6314
在我开始之前,简短的回答是“不用担心它”。我理解这种好奇,但在微观层面上,它将是不确定的,从宏观层面上,您需要关心的唯一事情是Dispatcher documentation,例如常规调度程序、固定调度程序、fork-join和线程池执行器之间的差异,以及消息传递排序文档中的排序保证。
此外,免责声明,我不声称自己是一个Maven的内部调度程序:我只是一个最终用户。但是我有点拖延,我想我应该分享一些我的调优观察,并在Akka源代码周围找点乐子。要获得更详细的答案,你也应该看看源代码。你正在寻找的大多数答案都在akka-actor/src/main/scala/akka/dispatch文件夹中。
先把免责声明放一边,让我先回答你的第二个问题。

  • “[调度员]是否会检查空闲参与者邮箱以及邮件?"*

调度员实际上并不检查任何东西:它完全是被动的。(我们将在后面看到。)它当然不会浪费任何时间检查空邮箱。这就是为什么一个调度程序可以扩展到数百万参与者。
你提出的更一般的问题“调度程序线程如何选择参与者?”很难用简单的方式回答。调度程序有很多种类型。几乎我能给予你的每一个答案都有一个例外。(例如,前面提到的其中线程专用于特定参与者的固定分派器以及被设计用于测试并在当前线程上运行所有调用的CallingThreadDispatcher)。但让我谈谈典型情况下的典型调度员。
调度器不选择参与者,调度器(在典型情况下)只是Java ExecutorServices的接口。典型场景如下:

  • 您向一个参与者的邮箱添加了一条消息。(从调度员的Angular 来看,我们对世界有一个颠倒的看法:我们与邮箱交互,而不是与演员交互。)
  • 如果尚未计划邮箱(如果邮箱中有邮件,则可能已经计划了邮箱),则邮箱将转到其调度程序并计划其自身。
  • 调度程序转到底层ExecutorService(假设是ForkJoinExecutor),并将一个任务入队以处理邮箱。
  • Javax 1 e3f1x就是complicated piece of scheduling,我并不认为自己是Maven,但简短的说法是,每个线程都有自己的队列,但是当它有一个空队列时,它能够从其他队列“窃取”任务。Java实现还能够动态调整它正在使用的线程数量,直到达到并行限制。这就是为什么我说“在微观级别”它“工作窃取动态线程是非常有效的,但是它不是确定性的。
  • 在某个时刻,与包含消息的邮箱相关的任务将被执行器选择,并且Runnable将被调用。
  • Runnable将首先处理邮箱中的系统消息,然后处理常规消息。这里也有各种例外,如优先级邮箱、存储、吞吐量限制等,但通常邮箱将处理消息(使用参与者的行为),直到邮箱为空或达到某个吞吐量限制。请注意,任务与邮箱而非消息绑定。

以上内容过于简化,忽略了一些边缘情况和性能优化,但这是30,000英尺的视图。
我希望这能有所帮助,因为我知道它充满了异常(邮箱和调度程序的设计是灵活的)和复杂性。但Akka是高度优化的,效率高得惊人。如果任何Akka开发人员想介入,告诉我我的描述哪里马虎了,请随意。但最终结果是我开始的地方:这里有多个抽象层,因此您得到的唯一顺序保证是文档中的顺序保证,但是即使每个消息完成的工作很小而消息数量很大,整个系统的吞吐量也非常有效。

相关问题