如何实现ReactiveMongo,以便将其视为非阻塞? [英] How is ReactiveMongo implemented so that it is considered non-blocking?

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

问题描述

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

但是,似乎从Play应用程序到Mongo服务器的通信必须发生在某个地方的某个线程上.如何实施?还将非常感谢您链接到Play,ReactiveMongo,Akka等源代码.

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

从下至上,

Play框架是一个异步Web框架.流是使用迭代器异步处理的.由于Play-core中的IO永远不会阻塞,因此Play中的线程池已调整为使用比传统Web框架更少的线程.

然后它谈论了有关ReactiveMongo的一些内容:

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

以下是有关使用期货的注释:

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

页面处理异步结果:

您无法通过将其包装在Future中而神奇地将同步IO转换为异步IO.如果您无法更改应用程序的体系结构以避免阻止操作,则有时必须执行该操作,并且该线程将被阻止.因此,除了将操作封装在Future中之外,还必须将其配置为在单独的执行上下文中运行,该上下文已配置了足够的线程来处理预期的并发性.

文档似乎在说ReactiveMongo是非阻塞的,因此您不必担心它会耗尽线程池中的许多线程.但是ReactiveMongo必须与Mongo服务器某处进行通信.

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

再次,链接到播放 Akka 等,将不胜感激.

解决方案

是的,确实,您仍然需要使用线程来执行任何类型的工作,包括与数据库的通信.重要的是该通信发生的准确程度.

ReactiveMongo在不使用阻塞I/O 的意义上不使用线程".像java.io.InputStream这样的常规Java I/O设施正在阻塞;这意味着从这样的InputStream读取或写入OutputStream会阻塞线程,直到另一侧"提供所需的数据或准备接受它为止.对于网络通信,这意味着线程 将被阻止.

但是,Java提供了 NIO API ,该API支持 non-blocking asynchronous I/O.我现在不想详细介绍它,但是基本的想法自然是,非阻塞I/O不允许阻塞需要与外界交换一些数据的线程:例如,这些线程可以轮询数据源以检查是否有可用数据,如果没有可用数据,它们将返回线程池并可用于其他任务.当然,这些功能是由底层操作系统提供的.

非阻塞I/O的确切实现细节通常隐藏在 Netty 之类的高级库中,因为它根本不适合使用.例如,Netty(正是ReactiveMongo使用的库)提供了不错的异步回调类API,该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天全站免登陆