Akka 和阻塞操作

Akka and blocking operations

我有一个 akka 系统,其中 99% 的请求都涉及阻止数据库调用。我想知道如最佳实践中所述,在单独 dispatcher\threadpool 中执行阻塞操作的系统是否有任何好处。

虽然 akka 线程将处于空闲等待状态,但线程池任务队列可能是内存溢出或开始拒绝新任务,actor 无法以某种方式处理这些任务。

我知道这是一个常见问题,但我找不到任何相关文章或讨论。

Akka 项目非常支持Reactive Manifesto。该文档假定通过使用 Akka,您也有兴趣根据 Reactive Manifesto 构建系统。

Reactive Manifesto 的一个关键部分是系统应该始终保持响应。如果您使用与主 Akka 路由基础结构相同的 dispatcher/thread 池来阻塞数据库操作,则所有 Akka 线程都可能被数据库操作占用,并且您的系统将有效地死锁,直到以下情况之一数据库操作完成。对于仅执行此任务的单个 JVM 上的简单系统来说,这可能不是问题,但很容易想到会导致此问题的新功能:

  1. 假设您想添加一个管理页面,显示当前正在运行的数据库请求数和等待由其中一个数据库线程执行的请求数。此页面应始终保持响应,即使所有 DB 线程都被阻塞,因此为该页面提供服务的代码应使用不能被 DB 阻塞的不同调度程序。
  2. 假设您想在多台不同的机器上向您的系统添加多个 JVM,以增加规模或提高具有一定容错能力的可靠性。这涉及要通过网络发送的各种八卦消息和心跳。如果这些系统消息由于阻塞数据库操作而延迟,则集群将无法正常工作。

出于另一个原因,单独的调度程序可能会有用。您可能希望限制对数据库的访问,以便您的系统不会使数据库过载。您可以使数据库调度程序成为一个固定大小的线程池,并将其用作一种粗略但有效的方式来限制您的数据库请求。另一种方法是与您的 actors 一起实现一些缓冲区,但这将需要大量额外的代码(尽管如果您担心 运行 由于任务过多等导致内存不足,您可能不得不这样做)。