Java 阻塞弹簧数据和反应弹簧数据之间的差异?

Java 阻塞弹簧数据和反应弹簧数据之间的差异?,java,spring-data,reactive-programming,nonblocking,project-reactor,Java,Spring Data,Reactive Programming,Nonblocking,Project Reactor,如果我们可以将标准的阻塞查询结果包装在一个反应流中,为什么我们需要非阻塞db连接器呢?Mongo、Redis等非阻塞连接器实际上是从数据源中传输数据,还是以阻塞方式获取数据,然后从内存中传输?查询Mongo的一个示例: public interface ItemReactiveRepository extends ReactiveMongoRepository<Item,String> { // } ... Flux<Item> itemsFlux = ite

如果我们可以将标准的阻塞查询结果包装在一个反应流中,为什么我们需要非阻塞db连接器呢?Mongo、Redis等非阻塞连接器实际上是从数据源中传输数据,还是以阻塞方式获取数据,然后从内存中传输?查询Mongo的一个示例:

public interface ItemReactiveRepository extends ReactiveMongoRepository<Item,String> {

    //
}

...
Flux<Item> itemsFlux = itemReactiveRepository.findAll();
公共接口项ReactiveRepository扩展了ReactiveMongoRepository{
//
}
...
Flux itemsFlux=itemReactiveRepository.findAll();

public interface ItemRepository扩展了MongoRepository{
// 
}
...
List itemsList=itemRepository.findAll();
通量项目通量=通量。可从项列表(itemsList);

如果有人能花点时间解释一下,或者加上一个链接,我会很感激的

简短的回答是可伸缩性

阻塞世界中(JDBC、JPA等),如果要同时执行多个数据库查询,那么需要的线程数量与要执行的并发数据库查询数量相同。在某一点之前,这一切都很正常。然而,线程并不是空闲的:它们需要内存,而上下文切换需要占用CPU时间。因此,并发性越强,系统就越难运行

这里是非阻塞IO(R2DBC、反应式Mongo驱动程序等)和反应式IO,它让您摆脱了每个连接模型的线程,并让您通过使用固定的低线程数(通常等于CPU内核数)实现相同的并发性。该模型提供了更高的可伸缩性


如果您只是将阻塞代码包装到一个反应流中,您就不会摆脱每连接一个线程的模型,您只会隐藏问题,并最终导致相同的可伸缩性问题。

反应代码并不仅仅是“使用不同的对象”。这是一种完全不同的编写代码的方式,以确保线程从不阻塞(或等待)其他事件发生。它要么忙着处理,要么准备好等待。这些对象只是以这种风格编写代码的副作用

理论上,我们可以使用现有Java对象编写代码,而只需使用“回调”。然而,尽管这种方法对于在UI上单击按钮是可行的,但如果您尝试扩展这种方法,您很快就会陷入“回调地狱”。这就是为什么我们有一些框架提供诸如
Flux
Mono
之类的对象,使我们能够以更明智、更强大的方式管理非阻塞代码

这些对象还提供了获取“标准”对象并包装它们的实用方法(例如
fromIterable()
just()
),这些方法在某些场景中很有用,但可能会被误用-您的第二个示例就是这样;一些人称之为“冒名顶替者”反应性代码的一个例子。它根本不是“反应性”或非阻塞性的,它只是将阻塞方法调用包装在反应性对象中,使它们看起来是反应性的。这是不好的,因为这意味着使用您的方法的人,假设他们是反应性的,因为他们看起来是反应性的,实际上会在非阻塞线程上调用阻塞代码。这要么会使整个实现崩溃,要么会使其速度惊人地减慢,然后可能意味着需要引入诸如Blockhound之类的工具来跟踪正在发生的事情


简单地说,不可能采用阻塞代码并使其成为非阻塞代码——因此,如果您认为自己以某种方式做到了这一点,那么您就错了。它必须从头开始编写(不幸的是,这就是为什么Java上的完整反应堆栈需要很长时间才能实现的原因)。然而,另一种方法很简单——你可以阻止任何你想要的反应调用。

一个数据库服务器可以同时处理多少个连接?我担心可伸缩性问题发生在服务器端的方式比发生在客户端的方式早,所以使客户端可伸缩是浪费时间。
public interface ItemRepository extends MongoRepository<User, String> {
    // 
}
...
List<Item> itemsList = itemRepository.findAll(); 
Flux<Items> itemsFlux = Flux.fromIterable(itemsList );