关于为什么gateway网关用webflux

前言

是么是webflux?

Spring Framework 中包含的原始 Web 框架 Spring Web MVC 是专门为 Servlet API 和 Servlet 容器构建的。反应式堆栈 Web 框架 Spring WebFlux 是在 5.0 版的后期添加的。它是完全非阻塞的,支持反应式流(Reactive Stream)背压,并在Netty,Undertow和Servlet 3.1 +容器等服务器上运行。

和springMVC有什么区别?

Spring WebFlux 是一个异步非阻塞式 IO 模型,通过少量的容器线程就可以支撑大量的并发访问。底层使用的是 Netty 容器,这点也和传统的 SpringMVC 不一样,SpringMVC 是基于 Servlet 的

接口的响应时间并不会因为使用了 WebFlux 而缩短,服务端的处理结果还是得由 worker 线程处理完成之后再返回给前端。

gateway为什么使用webflux 取代mvc?

WebFlux会比传统的MVC更快?如果是这样,为什么平时开发不用这个?带着这个疑惑我翻了大把的资料,全是异步编程,全是快,异步等。但是一个机器的资源就这么多,它又是如何更快的呢?如果快的话,为什么平时没人用呢?通过如下这个案例,来说一下我的理解

测试案例1
设置当前服务工作线程数为1,通过普通的同步写法,请求到接口。

 @GetMapping("/test3")
    public String stringMono3() {
        logger.info("threadName:{}", Thread.currentThread().getName());
        return "1";
    }

    @GetMapping("/test4")
    public String stringMono4() {
        logger.info("threadName:{}", Thread.currentThread().getName());
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "1";
    }

快速的请求test4和test3接口(保证先请求test4)日志如下:

2022-11-11 11:23:01.697 INFO 61844 — [ctor-http-nio-1] c.m.gateway.handler.FollBackController : threadName:reactor-http-nio-1
2022-11-11 11:23:11.704 INFO 61844 — [ctor-http-nio-1] c.m.gateway.handler.FollBackController : threadName:reactor-http-nio-1

仔细观察日志打印时间,可以看出当只有一个线程的时候,test4通过sleep方法让线程休眠,在休眠期间,该线程不做任何事情,导致请求test3接口时,也会等待很久。

这样可以想到,在真实场景中,如果有太多的这种阻塞操作,大量的线程在等待,会大量浪费计算机资源。能不能有一种方式,不让其等待呢?好比这个人没事的时候,就去干会别的活呢?

测试案例2

 @GetMapping("/test2")
    public Mono<String> stringMono2() {
        Mono<String> log = WebClient.create().post().uri("http://localhost:8080/test/sleep10").retrieve().bodyToMono(String.class);
        logger.info("threadName:{}", Thread.currentThread().getName());
        return log;
    }

    @GetMapping("/test3")
    public String stringMono3() {
        logger.info("threadName:{}", Thread.currentThread().getName());
        return "1";
    }

通过reactor来测试阻塞代码块。

test2接口为请求一个响应时长为10秒的接口。然后打印线程名
test3为直接打印线程名。
快速请求两个接口。日志打印如下:

2022-11-11 16:31:11.611  INFO 27436 --- [ctor-http-nio-1] c.m.gateway.handler.FollBackController   : threadName:reactor-http-nio-1
2022-11-11 16:31:12.797  INFO 27436 --- [ctor-http-nio-1] c.m.gateway.handler.FollBackController   : threadName:reactor-http-nio-1

从日志打印可以看出,线程1,在执行test/sleep10接口时,还执行了test3的方法。这就是非阻塞的概念。当线程进入等待状态时(如:http接口响应等待),可以做其它的事情。这样就可以用少量的线程做更多的事。

问题:为什么reactor这么好,不用他代替mvc模式呢?

个人以为,有两点原因。第一,一般我们的服务可以分为io密集型和cpu密集型。reactor模型仅在IO密集可以发挥出其优势。如网关,细想,gateway网关大部分都是在等待响应然后发挥,线程大把的时间处于等待,因此通过reactor编程可以更好的发挥其性能。第二,reactor学习成本高,不方便调试,用此框架时,需要多并发编程、nio等内容熟悉。

接口的响应时间并不会因为使用了 WebFlux 而缩短,服务端的处理结果还是得由 worker 线程处理完成之后再返回给前端。

webFlux与RestTemplate对比

WebClient是一个响应式客户端,它提供了RestTemplate的替代方法。它公开了一个功能齐全、流畅的API,并依赖于非阻塞I / O,使其能够比RestTemplate更高效地支持高并发性。WebClient非常适合流式的传输方案,并且依赖于较低级别的HTTP客户端库来执行请求,是可插拔的。

如果在你系统的类路径上有Spring WebFlux,就可以选择使用WebClient来调用远程REST服务。相比之下RestTemplate,这个客户端具有更多的函数感并且完全Reactive响应式的。您可以在Spring Framework文档WebClient的专用 部分中了解有关该内容的更多信息。

WebClient使用与WebFlux服务器应用程序相同的编解码器,并与服务器功能Web框架共享公共基本包,一些通用API和基础结构。API公开了Reactor Flux和Mono类型。默认情况下,它使用Reactor Netty作为HTTP客户端库,但其他人可以通过自定义ClientHttpConnector插入。

与RestTemplate相比,WebClient是:

非阻塞,Reactive的,并支持更高的并发性和更少的硬件资源。
提供利用Java 8 lambdas的函数API。
支持同步和异步方案。
支持从服务器向上或向下流式传输。

RestTemplate不适合在非阻塞应用程序中使用,因此Spring WebFlux应用程序应始终使用WebClient。在大多数高并发场景中,WebClient也应该是Spring MVC中的首选,并且用于编写一系列远程,相互依赖的调用

删除线格式 官网明确指出,SpringWebFlux并不是让你的程序运行的更快(相对于SpringMVC来说),而是在有限的资源下提高系统的伸缩性,因此当你对响应式编程非常熟练的情况下并将其应用于新的系统中,还是值得考虑的,否则还是老老实实的使用WebMVC吧

你可能感兴趣的:(#,springcloud,gateway,servlet,java)