Spring MVC(异步)与Spring WebFlux的区别

77

我正在尝试了解Spring WebFlux。到目前为止,我发现它具有以下特点:核心是反应式的;没有Servlet API;没有每个请求一个线程;支持HTTP 2、服务器推送和application/stream+json。

但是Spring MVC中的异步调用与之有何区别?我的意思是,在Spring MVC中,当您返回Future、DeferredResult等时,请求处理程序(控制器方法)中的逻辑将在单独的线程中执行,因此您可以从保存线程池资源以分派请求中受益。

那么,请您指出这些差异的相关性吗?为什么WebFlux在这方面更好呢?

非常感谢您的时间!


5
响应式编程是推送驱动的,并且使用单个调度程序线程(非常高效),而旧模型仍然受限于线程池中的线程数量。 - M. Deinum
@M. Deinum但在这种情况下,我受限于一个线程可以处理的负载。为什么不使用多个线程,而不仅仅是一个拥有多核系统? - Dmitry Senkovich
2
它是一个事件分发线程,这是完全不同的模型。它只分发事件(非常快速),而另一个模型仍然是阻塞的。 - M. Deinum
@M. Deinum 好的,非常有趣,我一定要看看,谢谢! - Dmitry Senkovich
@M. Deinum,请分享请求生命周期。 - gstackoverflow
@M. Deinum,Spring可以使用servlet 3.1而无需WebFlux(使用CompletableFuture作为返回类型+Tomcat 8.5+)。 - gstackoverflow
2个回答

56
Servlet异步模型在容器线程(1 Servlet请求/线程模型)和应用程序中的请求处理之间引入了异步边界。处理可以在不同的线程上发生或等待。最终,您必须将其分派回容器线程并以阻塞方式读取/写入(InputStreamOutputStream本质上是阻塞API)。
使用该模型,您需要许多线程来实现并发(因为其中许多线程可能会被阻塞等待I/O)。这会消耗资源,并且这可能是一种权衡,具体取决于您的用例。
使用非阻塞代码,您只需要少量线程即可同时处理大量请求。这是一种不同的并发模型;像任何模型一样,它都有其优点和权衡。
有关该比较的更多信息,请参见此Servlet vs. Reactive stacks talk

2
你能详细说明一下吗?即使对于响应式WebFlux,我们也必须等待写入socket。据我所知,在异步servlet api的情况下,容器线程必须将请求传递到应用程序线程池中等待空闲工作线程,之后传递线程就可以释放并用于另一个请求,而不需等待请求完成。你为什么说“使用这种模型需要许多线程才能实现并发”? - gstackoverflow
我没有看到文本版本。对于我来说,看英语视频并理解棘手的细节有点复杂。 - gstackoverflow
这就是我回答的要点。简而言之,非阻塞 I/O 与阻塞 I/O。 - Brian Clozel
2
抱歉,我不太清楚。在DefferedResult的情况下,Tomcat线程只是将请求传递给应用程序线程池 - 这是如此短的操作,因此它已准备好处理另一个请求。WebFlux提供了哪些杀手级功能? - gstackoverflow
3
根据您的回答,我理解您对DefferedResult的关注在于这句话:“最终,您必须将任务调度回容器线程,并以阻塞方式进行读/写操作(InputStream和OutputStream本身是阻塞API)。” 您想说的是WebFlux有一些神奇的套接字可以异步读写吗?这是否可能? - gstackoverflow
显示剩余6条评论

10

Servlet API是阻塞I/O,每个HTTP请求需要1个线程。Spring MVC异步依赖于Servlet API,它只提供容器线程和请求处理线程之间的异步行为,而不是端到端。

另一方面,Spring WebFlux通过使用HTTP套接字和通过套接字推送数据块来固定数量的线程实现并发。这种机制称为事件循环,这是由Node.js推广的一个想法。这种方法是可扩展和具有弹性的。 Spring 5的spring-webflux使用事件循环方法提供异步行为。

更多内容可以阅读:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接