使用Scala Akka框架阻止CLI调用

时间:2012-10-16 13:17:31

标签: scala akka blocking

我对Akka& amp; Scala,但我想使用Akka作为通用框架来汇集来自各种Web工具和cli命令的信息。

我理解一般的原则,在Actor模型中,非常希望不让actor阻塞。在http请求的情况下,存在异步http客户端(例如Spray),这意味着我可以在Actor框架内异步处理请求。

但是,我不确定将actor与现有阻塞API调用(如scala ProcessBuilder / ProcessIO库)结合使用时的最佳方法是什么。在发布这些CLI命令方面,我期望相对较少的并发性,例如也许在12核计算机上最多执行10次并发CLI调用。

让一个actor管理这些CLI命令,将实际工作分配给根据需要创建的Futures更好吗?或者仅仅维护一组由PinnedDispatcher支持的独立actor会更干净吗?或其他什么?

1 个答案:

答案 0 :(得分:4)

来自Akka文档(http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html#Blocking_Needs_Careful_Management):

阻止需要谨慎管理

在某些情况下,进行阻塞操作是不可避免的,即让线程在不确定的时间内进入休眠状态,等待外部事件发生。示例是传统的RDBMS驱动程序或消息传递API,以及通常(网络)I / O在封面下发生的根本原因。面对这种情况时,您可能想要将阻塞调用封装在Future中并使用它,但是这个策略太简单了:当应用程序运行时,您很可能会发现瓶颈或内存或线程耗尽在负荷增加的情况下。

“阻塞问题”的充分解决方案的非详尽清单包括以下建议:

  • 在一个actor(或由路由器[Java,Scala]管理的一组actor)中进行阻塞调用,确保配置一个专用于此目的或足够大小的线程池。
  • 在Future中进行阻塞调用,确保在任何时间点对此类调用的数量设置上限(提交此类无限数量的任务将耗尽您的内存或线程限制)。
  • 在Future中执行阻塞调用,提供一个线程池,其中包含适用于运行应用程序的硬件的线程数上限。 专用一个线程来管理一组阻塞资源(例如,驱动多个通道的NIO选择器),并在事件发生时调度事件。

第一种可能性特别适用于本质上是单线程的资源,例如数据库句柄,传统上一次只能执行一个未完成的查询并使用内部同步来确保这一点。一种常见的模式是为N个actor创建路由器,每个actor包含一个数据库连接并处理发送到路由器的查询。然后必须调整数量N以获得最大吞吐量,这取决于在哪个硬件上部署哪个DBMS。“