scala - ReactiveMongo 是如何实现的,因此它被认为是非阻塞的?

标签 scala playframework reactive-programming reactivemongo iterate

阅读有关 Play 框架和 ReactiveMongo 的文档让我相信 ReactiveMongo 的工作方式是它使用很少的线程并且从不阻塞。

但是,从 Play 应用程序到 Mongo 服务器的通信似乎必须在某个线程上发生。这是如何实现的?也非常感谢提供 Play、ReactiveMongo、Akka 等源代码的链接。

Play 框架在此页面上包含一些关于此的文档 about thread pools .它开始:

Play framework is, from the bottom up, an asynchronous web framework. Streams are handled asynchronously using iteratees. Thread pools in Play are tuned to use fewer threads than in traditional web frameworks, since IO in play-core never blocks.



然后它谈到了一些关于 ReactiveMongo 的内容:

The most common place that a typical Play application will block is when it’s talking to a database. Unfortunately, none of the major databases provide asynchronous database drivers for the JVM, so for most databases, your only option is to using blocking IO. A notable exception to this is ReactiveMongo, a driver for MongoDB that uses Play’s Iteratee library to talk to MongoDB.



以下是使用 Futures 的注意事项:

Note that you may be tempted to therefore wrap your blocking code in Futures. This does not make it non blocking, it just means the blocking will happen in a different thread. You still need to make sure that the thread pool that you are using there has enough threads to handle the blocking.



页面 Handling Asynchronous Results 上的 Play 文档中也有类似的注释。 :

You can’t magically turn synchronous IO into asynchronous by wrapping it in a Future. If you can’t change the application’s architecture to avoid blocking operations, at some point that operation will have to be executed, and that thread is going to block. So in addition to enclosing the operation in a Future, it’s necessary to configure it to run in a separate execution context that has been configured with enough threads to deal with the expected concurrency.



文档似乎在说 ReactiveMongo 是非阻塞的,因此您不必担心它会占用线程池中的大量线程。但是 ReactiveMongo 必须在某处与 Mongo 服务器通信。

这种通信是如何实现的,以便 Mongo 不会用完 Play 的默认线程池中的线程?

再次链接到 Play 中的特定文件, ReactiveMongo , Akka等,将不胜感激。

最佳答案

是的,确实,您仍然需要使用线程来执行任何类型的工作,包括与数据库的通信。重要的是这种沟通究竟是如何发生的。

ReactiveMongo 在某种意义上“不使用线程”,即它不使用阻塞 I/O。常用的 Java I/O 工具,如 java.io.InputStream正在阻塞;这意味着从这样的 InputStream 读取或写信给 OutputStream阻塞线程,直到“另一端”提供所需的数据或准备好接受它。对于网络通信,这意味着线程将被阻塞。

但是,Java 提供了 NIO API它支持非阻塞和异步 I/O。我现在不想深入了解它的细节,但基本思想自然是非阻塞 I/O 允许不阻塞需要与外界交换一些数据的线程:例如,这些线程可以轮询数据源,检查是否有数据可用,如果没有,则返回线程池,可用于其他任务。当然,在那里这些设施是由底层操作系统提供的。

非阻塞 I/O 的具体实现细节通常隐藏在高级库中,例如 Netty因为它根本不好用。例如,Netty(这正是 ReactiveMongo 使用的库)提供了很好的类似异步回调的 API,它非常易于使用,但功能强大且富有表现力,可以构建具有高吞吐量的复杂 I/O 密集型应用程序。

所以,ReactiveMongo 使用 Netty 与 Mongo 数据库服务器对话,而且由于 Netty 是异步网络 I/O 的实现,ReactiveMongo 真的不需要长时间阻塞线程。

关于scala - ReactiveMongo 是如何实现的,因此它被认为是非阻塞的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25618259/

相关文章:

scala - 什么是基于规则验证的 Scala 惯用方法?

scala - Spark Streaming 有状态网络字数统计

java - Java 扩展是否可以在 Play Framework 上运行?

playframework - 类型安全存储库和激活器的问题

scala - 在 OSX Lion for Scala 上安装 JDK

java - 有没有直接的方法将一个 s3 目录复制到 java 或 scala 中的另一个目录?

scala - 如何在 Scala Play 框架中添加按钮处理程序?

java - 做运营商而不是整个订阅者

java - 使用 Reactive Streams 的 Reactive Pull-Based BackPressure

java - react 堆项目 : ConnectableFlux auto-connecting on demand