我有一个Master actor,它使用路由器创建Worker actor。每个Worker actor执行多个HTTP连接。
从几个来源我了解到如果actor进行了一些阻塞操作,那么将阻塞操作包装到这个构造中会更好:
val resFut = future {
blocking {
executeQuery()
}
}
resFut pipeTo sender
但后来我读到official topic关于处理Akka中的阻塞操作,我很惊讶该主题建议只使用路由器进行阻塞操作(替代Futures):
在一个演员(或由一个演员管理的一组演员)中进行阻塞调用 路由器),确保配置一个线程池 专用于此目的或足够大小。
所以我的问题是:我是否应该在我的Worker actor中使用以下构造,即使它是由路由器支持的?
future {
blocking {
executeQuery()
}
}
或者只是为路由器配置和使用另一个调度程序将帮助我实现相同的好处?
答案 0 :(得分:2)
你可以做任何一件事。您引用的文档基本上是说〜要么使用路径与工作者,单个演员或未来。
整个想法是一个线程可能会阻塞而你想要正确地管理它 - 你应该对阻塞的线程数有一个上限。这可以通过路由器控制路由数来实现,也可以通过手动控制并发运行数或使用有界线程池来实现。
在任何一种情况下,如果您使用阻止使用其父(控制器)与客户端通信的actor。这样,如果工作者死于异常或超时,您的客户端仍将收到响应。因此,控制器永远不会崩溃并响应多客户端请求。
除非你觉得方便(例如使用带超时的pipeTo),否则不需要同时使用每个请求的actor模式和将来包装阻塞代码。
要控制路由器中的actor数量,有2个相关的配置级别。较低级别的配置是您的Dispatcher config,它定义了要使用的线程数。最重要的是Router config使用nrOfInstances
来控制可以存在多少路由 - 上限。您应该将调度程序中的线程池大小设置为NRouters * NRoutees周围的阻塞操作。