通过示例了解Akka的消息传递机制

11

我有相当多的Apache Camel(路由/调解/编排引擎;轻量级ESB)经验,现在我正在努力理解Akka之间的区别:

  • 调度程序( Dispatcher , PinnedDispatcher , CallingThreadDispatcher )
  • 路由器
  • 事件总线

根据文档:

调度程序是:

...是使Akka Actors“工作”的原因,可以说它是机器的引擎。

但这并没有真正解释调度程序是什么或者它与Actor的关系是什么。

路由器是:

消息可以通过路由器发送,以有效地将它们路由到目标Actor,称为其路由。路由器可以在Actor内部或外部使用,您可以自行管理路由或使用具有配置功能的独立路由Actor。但它听起来非常像调度程序。

是:

[一种]路由器[创建作为子Actor的路由],并在它们终止时从路由器中删除它们。

是:

[一种]Actor[其中routees]在路由器外部创建,路由器使用Actor选择发送消息到指定路径,而不监视终止。

事件总线是:

...是向Actor组发送消息的方法

这听起来就像调度程序和路由器。

所以我的主要问题是:

  • 调度程序,路由器和事件总线之间的区别是什么,每个何时使用?
  • 何时使用池与组?
1个回答

22
一个调度程序基本上是一个线程池。Akka使用调度程序来执行多个操作(比如将消息排队到正确的邮箱中,或从actor邮箱中提取消息并进行处理)。每当需要执行其中的一项操作时,就会选择一个线程池中的线程来执行它。Akka默认带有default-dispatcher,可以在reference.conf中找到与之相关的配置信息。您已经在使用default-dispatcher,但是您可以定义不同的调度程序,以确保为其他目的(例如在使用akka-remote或akka-cluster时用于netty线程)保留独立的线程池。

Akka中的路由器是一个actor,它使用某种路由逻辑将消息路由到路由列表中的路由实例。根据逻辑,有许多类型的路由器:广播(Broadcast)、负载均衡(Balancing)、循环(RoundRobin)等,您可以在akka文档中找到所有这些类型。路由器的路由实例可以是池或组。路由器最受欢迎的用例之一是垂直扩展应用程序,这意味着最大化使用系统中所有可用的CPU(同时使用多个线程)。

意味着路由实例将按需为给定类型创建。例如,您可能希望使用3个实例的MyFancyActorRandomPool。Akka将创建三个MyFancyActor的actor和第四个作为实际路由器的actor。每当路由器actor接收到消息时,都会将消息转发到其中的3个MyFancyActor actor之一。池负责重新启动actor并监视它们的生命周期,以确保有n个实例正在运行。

是指在定义路由器之前创建路由者。一旦您定义了路由器,您需要传递先前创建的路由者 actor 列表。组不会监视您的 actors 生命周期,因此您需要自己处理。

事件总线是用于订阅特定类型消息的频道,与 actor 一起使用。如果有这种特定类型的消息,您的 actor 将收到它。这用于一些 Akka 内部,例如当消息无法到达其目标或关于集群形成的事件(在 akka-cluster 中)时订阅 DeadLetters。您将使用此功能来了解发生在您的 ActorSystem 中的事件。


精彩的回答,感谢 @hveiga (+1) - 有几个跟进问题:(1) 所以听起来 Dispatcher 就像是一个路由器,但是在 Akka 中用于消息传递和其他低级别的线程处理,因此,我永远不会直接向 Dispatcher 发送消息,是吗?(2) 听起来事件总线实际上就像是一个系统范围的邮箱。 但是如果我已订阅从总线接收特定类型的消息,那么是否会阻止其他类型的 actors 也接收相同的消息呢?再次感谢! - smeeb
Dispatcher 对你来说是透明的。它们会调度线程执行操作。你不能向 dispatcher 发送消息。需要注意的是,dispatcher 不是 actor,而 router 是。关于事件总线,你对系统范围邮箱的定义可能是正确的。然而,我不知道内部情况,但我真的怀疑 Akka 的开发人员会制作一些阻塞的东西。我认为它不会阻塞。可能实现为一个 Router,每种类型的消息的路由列表(订阅者)随时间变化。 - hveiga
为什么我们需要三个相同演员的实例?我以为Actor一直只有一个实例?消息是通过Dispatcher传递给Actor的,对吗? - Diego Ramos
您可能需要多个相同演员的实例。由于在某一时刻一个演员只能处理一个消息,因此可能存在需要同时处理多个消息的情况。实现这一目标的方法是拥有池或组的演员。 - hveiga
谢谢,@hveiga (+1) - 我有一个快速问题想要跟进。我很好奇您在推荐消息处理池大小时是如何得出数字“3”的。我理解我们可能希望同时处理多个消息,因此创建一个可以处理我们想要并行处理的最大消息数量的池是有意义的。但是,如果我们将池设置得太大,比如说1000,会发生什么?这是一种资源浪费吗?如果是,您能否解释一下原因?我真的很感激您能更详细地阐述一下吗?谢谢 - Zvi Mints

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接