4

我对 Akka 和 Scala 比较陌生,但我想使用 Akka 作为通用框架来收集来自各种 Web 工具和 cli 命令的信息。

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

但是,我不确定将参与者与现有的阻塞 API 调用(例如 scala ProcessBuilder/ProcessIO 库)结合起来的最佳方法是什么。在发出这些 CLI 命令方面,我预计并发量相对较少,例如,可能在 12 核机器上执行最多 10 个并发 CLI 调用。

让单个参与者管理这些 CLI 命令,将实际工作分配给根据需要创建的 Future 是否更好?或者仅仅维护一组由 PinnedDispatcher 支持的独立参与者会更干净吗?或者是其他东西?

4

1 回答 1

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 个参与者创建一个路由器,每个参与者都包装一个 DB 连接并处理发送到路由器的查询。然后必须调整数字 N 以获得最大吞吐量,这将取决于部署在什么硬件上的 DBMS。”

于 2012-10-16T13:31:51.467 回答