Spring MVC is built on the Servlet API and uses a synchronous blocking I/O architecture whth a one-request-per-thread model.
Spring MVC 构建于 Servlet API 之上,使用的是同步阻塞式 I/O 模型,什么是同步阻塞式 I/O 模型呢?就是说,每一个请求对应一个线程去处理。
Spring WebFlux is a non-blocking web framework built from the ground up to take advantage of multi-core, next-generation processors and handle massive numbers of concurrent connectio
Spring WebFlux 是一个异步非阻塞式的 Web 框架,它能够充分利用多核 CPU 的硬件资源去处理大量的并发请求。
ns.
二、WebFlux 的优势&提升性能?
WebFlux 内部使用的是响应式编程(Reactive Programming),以 Reactor 库为基础, 基于异步和事件驱动,可以让我们在不扩充硬件资源的前提下,提升系统的吞吐量和伸缩性。
看到这里,你是不是以为 WebFlux 能够使程序运行的更快呢?量化一点,比如说我使用 WebFlux 以后,一个接口的请求响应时间是不是就缩短了呢?
抱歉了,答案是否定的!以下是官方原话:
Reactive and non-blocking generally do not make applications run faster.
WebFlux 并不能使接口的响应时间缩短,它仅仅能够提升吞吐量和伸缩性。
三、WebFlux 应用场景
上面说到了, Spring WebFlux 是一个异步非阻塞式的 Web 框架,所以,它特别适合应用在 IO 密集型的服务中,比如微服务网关这样的应用中。
PS: IO 密集型包括:磁盘IO密集型, 网络IO密集型,微服务网关就属于网络 IO 密集型,使用异步非阻塞式编程模型,能够显著地提升网关对下游服务转发的吞吐量。
首先你需要明确一点就是:WebFlux 不是 Spring MVC 的替代方案!,虽然 WebFlux 也可以被运行在 Servlet 容器上(需是 Servlet 3.1+ 以上的容器),但是 WebFlux 主要还是应用在异步非阻塞编程模型,而 Spring MVC 是同步阻塞的,如果你目前在 Spring MVC 框架中大量使用非同步方案,那么,WebFlux 才是你想要的,否则,使用 Spring MVC 才是你的首选。
在微服务架构中,Spring MVC 和 WebFlux 可以混合使用,比如已经提到的,对于那些 IO 密集型服务(如网关),我们就可以使用 WebFlux 来实现。
选 WebFlux 还是 Spring MVC? This is not a problem!
在构建响应式 Web 服务上,Spring 5 中引入了全新的编程框架,那就是 Spring WebFlux。作为一款新型的 Web 服务开发框架,它与传统的 WebMVC 相比具体有哪些优势呢?今天我们就针对这个话题展开讨论。
1. WebFlux使用场景
WebFlux 用于构建响应式 Web 服务。在详细介绍 WebFlux 之前,我们先梳理一下这个新框架的应用场景,了解应用场景才能帮助我们对所要采用的技术体系做出正确的选择。
因为 Reactor 这样的响应式库可以帮助我们构建一个异步的非阻塞流,并且为开发人员屏蔽了底层的技术复杂度。而基于 Reactor 框架的 WebFlux 进一步降低了开发响应式 Web 服务的难度。
微服务架构的兴起为 WebFlux 的应用提供了一个很好的场景。我们知道在一个微服务系统中,存在数十乃至数百个独立的微服务,它们相互通信以完成复杂的业务流程。这个过程势必会涉及大量的 I/O 操作,尤其是阻塞式 I/O 操作会整体增加系统的延迟并降低吞吐量。如果能够在复杂的流程中集成非阻塞、异步通信机制,我们就可以高效处理跨服务之间的网络请求。针对这种场景,WebFlux 是一种非常有效的解决方案。
2. WebMVC 和WebFlux
2.1 Spring WebMvc
Java中的传统的Web容器都是基于Servlet规范来实现的,Spring WebMvc 作为一种经典的Web框架实现,同样也是基于Servlet来实现的。Spring MVC 相信大家都非常熟悉,也是主流的开发框架。这里不在详细介绍,在我的计划中后面会出一系列源码阅读的文章包括Spring、WebMvc和Mybatis等。这里放一张架构图用来和WebFlux作为对比。
2.2 Spring WebFlux
由于Spring WebMVC 在实现上并不允许在整个请求生命周期中都采用非阻塞式的操作方式。因此,Spring 在尽量沿用原有的开发模式以及 API 设计上提供了支持异步非阻塞的 Spring WebFlux 框架。
在使用WebFlux和WebMvc实际的使用并没有太大的区别,实际上WebFlux的核心组件基本都是SpringMvc核心组件的异步非阻塞实现版本。所以在有了差别不大的开发体验。
2.3 对比两种实现的处理模型
Spring WebMvc是一种同步阻塞的处理模型,也就是说当请求过来时,工作线程开始处理请求后,然后开始阻塞等待DB或者IO操作完成,当IO结束是返回响应结果。
模型大概如上,可以看到工作线程的实际处理时间远小于花费在阻塞操作上的时间。这意味着工作线程会被 I/O 读取或写入数据这一操作所阻塞。从这个简单的图中,我们可以得出结论,线程效率低下。同时,因为所有请求是排队的,相当于一个请求队列,所以接受请求和处理请求这两部分操作实际上是可以共享等待时间的。WebFlux 构建在非阻塞 API 之上,这意味着没有操作需要与 I/O 阻塞线程进行交互。接受和处理请求的效率很高,如下图所示。
将上图中所展示的异步非阻塞请求处理与前面的阻塞过程进行比较,我们会注意到,现在没有在读取请求数据时发生等待,工作线程高效接受新连接。然后,提供了非阻塞 I/O 机制的底层操作系统会告诉我们请求数据是否已经接收完成,并且处理器可以在不阻塞的情况下进行处理。
2.4 性能差异
引用维护Spring 框架的 Pivotal 公司软件开发主管 Biju Kunjummen 的测试结果来对这一问题进行解答。
在 Biju Kunjummen 的测试用例中,他分别基于 WebMVC 所提供的阻塞式 RestTemplate 以及 WebFlux 所提供的非阻塞式 WebClient 工具类对远程 Web 服务发起请求。对于不同组的并发用户(300、1000、1500、3000、5000),他分别发送了一个 delay 属性设置为 300 ms 的请求,每个用户重复该场景 30 次,请求之间的延迟为 1 到 2 秒。测试用例中使用了 Gatling 这款工具来执行压测。
这里我们截取 300 和 3000 并发用户场景下的结果进行对比,如下面两张图所示。
可以看出在300并发时,两者并没有太大区别,当并发量上升时WebFlux就有压倒式优势了,所以异步框架更适合高并发的业务场景。
3. 总结
本节主要对比了WebMvc 和 WebFlux两个Web框架,Spring已经为我们开发做了很大努力了,所以在合适的场景下这种异步框架还是非常可行的。但是还要考虑后期其它异步框架是否能够完善,全链路异步才能发挥异步最大的优势。