Akka路由器、Futures和阻塞操作

Akka router, Futures and blocking operation

我有一个 Master actor,它使用路由器创建 Worker actors。每个 Worker actor 执行多个 HTTP 连接。

我从几个来源了解到,如果 actor 执行一些阻塞操作,那么最好将阻塞操作包装到这个结构中:

val resFut = future {
  blocking {
    executeQuery()
  }
}

resFut pipeTo sender

但后来我阅读了 official topic 关于在 Akka 中处理阻塞操作的内容,令我惊讶的是主题建议只使用路由器进行阻塞操作(作为 Futures 的替代方案):

Do the blocking call within an actor (or a set of actors managed by a router), making sure to configure a thread pool which is either dedicated for this purpose or sufficiently sized.

所以我的问题是:我是否应该在我的 Worker actor 中使用以下结构,即使它由路由器支持?

future {
      blocking {
        executeQuery()
      }
}

或者只是为路由器配置和使用另一个调度程序将帮助我实现同样的好处?

你可以做任何一个。您参考的文档基本上说〜要么使用带有工人演员,单个演员或期货的路由器。

整个想法是一个线程可能会阻塞,而您想正确地管理它——您应该对阻塞的线程数有一个上限。这可以通过控制路由数量的路由器来实现,或者通过手动控制并发运行的数量或使用有界线程池来实现。

在任何一种情况下,如果您使用阻止使用其父级(控制器)与客户端通信的参与者。这样,如果 worker actor 因异常或超时而死亡,您的客户端仍会收到响应。因此,控制器不应该崩溃并响应多客户端请求。

除非您觉得方便(例如,使用带超时的 pipeTo),否则不需要同时具有 actor-per-request 模式和未来包装阻塞代码。

为了控制路由器中的参与者数量,有 2 个相关级别的配置。较低级别的配置是您的 Dispatcher config that defines number of threads to use. On top of it is Router config,它使用 nrOfInstances 来控制可以存在多少路由 - 上限。您应该将调度程序中的线程池大小设置为 NRouters * NRoutees 附近的某个位置以进行阻塞操作。