04 WebFlux和SpringMVC有什么区别
在构建响应式 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已经为我们开发做了很大努力了,所以在合适的场景下这种异步框架还是非常可行的。但是还要考虑后期其它异步框架是否能够完善,全链路异步才能发挥异步最大的优势。
本文所有图片均来着拉钩教育的一遍文章《Spring 响应式编程实战》大家如果有兴趣可以参考学习。