ReactiveMongo 是如何实现的,所以它被认为是非阻塞的? [英] How is ReactiveMongo implemented so that it is considered non-blocking?

查看:27
本文介绍了ReactiveMongo 是如何实现的,所以它被认为是非阻塞的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

Play 框架在此页面上包含一些关于此的文档关于线程池.开始了:

<块引用>

Play 框架自下而上是一个异步 Web 框架.流使用迭代器异步处理.Play 中的线程池经过调整以使用比传统 Web 框架更少的线程,因为 play-core 中的 IO 永远不会阻塞.

然后谈了一点关于 ReactiveMongo:

<块引用>

典型的 Play 应用程序最常被阻塞的地方是它与数据库的对话.不幸的是,没有一个主要数据库为 JVM 提供异步数据库驱动程序,因此对于大多数数据库,您唯一的选择是使用阻塞 IO.一个值得注意的例外是 ReactiveMongo,它是 MongoDB 的驱动程序,它使用 Play 的 Iteratee 库与 MongoDB 对话.

以下是关于使用 Futures 的说明:

<块引用>

请注意,您可能会因此将阻塞代码包装在 Futures 中.这并不使它成为非阻塞,它只是意味着阻塞将发生在不同的线程.您仍然需要确保您在那里使用的线程池有足够的线程来处理阻塞.

Handling Asynchronous Results:

<块引用>

你不能通过将同步 IO 包装在 Future 中神奇地将它变成异步.如果您无法更改应用程序的架构以避免阻塞操作,在某些时候该操作将不得不执行,并且该线程将阻塞.因此,除了将操作封装在 Future 中之外,还需要将其配置为在单独的执行上下文中运行,该上下文已配置了足够的线程来处理预期的并发.

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

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

再次链接到Play中的特定文件,ReactiveMongoAkka 等, 将不胜感激.

解决方案

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

ReactiveMongo不使用线程",因为它不使用阻塞 I/O.像 java.io.InputStream 这样的常用 Java I/O 工具是阻塞的;这意味着从这样的 InputStream 读取或写入 OutputStream 会阻塞线程,直到另一端"提供所需的数据或准备好接受它.对于网络通信,这意味着线程被阻塞.

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

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

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

Reading the documentation about the Play Framework and ReactiveMongo leads me to believe that ReactiveMongo works in such a way that it uses few threads and never blocks.

However, it seems that the communication from the Play application to the Mongo server would have to happen on some thread somewhere. How is this implemented? Links to the source code for Play, ReactiveMongo, Akka, etc. would also be very appreciated.

The Play Framework includes some documentation about this on this page about thread pools. It starts off:

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.

It then talks a little bit about 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.

Following is a note about using 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.

There is a similar note in the Play documentation on the page Handling Asynchronous Results:

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.

The documentation seems to be saying that ReactiveMongo is non-blocking, so you don't have to worry about it eating up a lot of the threads in your thread pool. But ReactiveMongo has to communicate with the Mongo server somewhere.

How is this communication implemented so that Mongo doesn't use up threads from Play's default thread pool?

Once again, links to the specific files in Play, ReactiveMongo, Akka, etc, would be very appreciated.

解决方案

Yes, indeed, you still need to use threads to perform any kind of work, including communication with the database. What's important is how exactly this communication happens.

ReactiveMongo "does not use threads" in a sense that it does not use blocking I/O. Usual Java I/O facilities like java.io.InputStream are blocking; this means that reading from such an InputStream or writing to OutputStream blocks the thread until the "other side" provides the required data or is ready to accept it. For network communication this means that threads will be blocked.

However, Java provides NIO API which supports non-blocking and asynchronous I/O. I don't want to get into its details right now, but the basic idea, naturally, is that non-blocking I/O allow not to block threads which need to exchange some data with the outside world: for example, these threads can poll the data source to check if there is some data available, and if there is none, they return to the thread pool and can be used for other tasks. Of course, down there these facilities are provided by the underlying OS.

Exact implementation details of non-blocking I/O is usually hidden inside high-level libraries like Netty because it is not at all nice to use. Netty (which is exactly the library ReactiveMongo uses), for example, provides nice asynchronous callback-like API which is really easy to use but is also powerful and expressive enough to allow building complex I/O-heavy applications with high throughput.

So, ReactiveMongo uses Netty to talk with Mongo database server, and because Netty is an implementation of asynchronous network I/O, ReactiveMongo really does not need to block threads for a long time.

这篇关于ReactiveMongo 是如何实现的,所以它被认为是非阻塞的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆