1. Webflux介绍

        Webflux是一种异步非阻塞的IO模型,当有请求过来时,它会将请求交由worker线程去处理,这样就可以极大的提升吞吐量,所以他比较适合用于IO密集型的场景。

        webflux虽然可以给我带来吞吐量的提升,但是同时也带了一些问题,如调试困难,有一定的学习成本,此外目前仅有少数数据库支持异步非阻塞查询,如redis支持,而mysql不支持。它使用netty作为服务端框架,网络通信性能很高,但是我们在准备引入该技术的时候也需要十分谨慎。

在SpringBoot官方也给出了相关建议:

  1. 如果你的项目目前使用的时SpringMvc且运行良好那就没有必要使用Webflux,SpringMvc的编程方式易编写也易理解,同时还有大量的类库可供使用。
  2. 如果你已经使用了异步非阻塞的编程方式,那么可以切换到webflux,webflux提供了更加丰富的功能
  3. 如果你对轻量级、java8的lambdas函数式编程的web框架感兴趣,那么在一些小型项目上可以使用。
  4. 在微服务架构下,你可以同时使用springmvc和wenflux,它们的在基础注解模型上是一样的
  5. 如果你依赖了持久化层的API(JDBC、JPA)或者网络API,对于基础架构来说springmvc是最好的选择
  6. 如果你的springmvc应用调用远程服务,可以尝试使用webclient。你可以直接从controller方法中获取到reactive类型。
  7. 如果你在一个大型团队,那么要谨慎考虑切换的成本,webflux的学习曲线还是比较陡峭。

2. Reactor框架介绍

Springboot官网为我们提供了关于reactive 的技术栈,如下图所示:

Webflux主要技术依赖有:Reactive Streams反应式编程标准和规范、基于reactive streams的反应式编程框架和以reactive为基础实现web领域的反应式编程框架。

Reactive Streams是一套基于jvm面向流式类库的标准和规范,它要求:

  1. 具有处理无限数量数据的能力
  2. 按序处理数据
  3. 异步非阻塞的传递数据
  4. 必须实现非阻塞的背压

Reactive api规范组件:

  1. Publisher:数据发布者
  2. Subscriber:数据订阅者
  3. Subscription:订阅信号
  4. Processor:处理器(包含了发布者和订阅者的混合体)

Reactive操作符:

1. Map操作符:对每一个数据进行转换操作,如,每个数据除2,当处理完交由消费端。

2. Flatmap操作符:有时候我们一个元素需要映射成一个元素序列,将该序列压平然后合并成更大的元素序列。

3. Filter操作符:指将不符合条件的元素过滤掉,不发给消费端。

 

4. Zip操作符:将两个publisher的序列合并输出。 

 

Reactor与java 8 Stream区别:虽然从写法来看感觉一样,其实是形似神不似。Reactor采用的是push模式,服务端推送数据给客户端消费,它是异步反应式模式;而stream是pull模式是同步的命令式程序。

Reactor线程模型:

1. 创建线程方式:

Schedulers.immediate():当前线程

Schedulers.single():可重用的单线程

Schedulers.elastic():弹性线程池

Schedulers.parallel():固定大小线程池

Schedulers.fromExecutorService():自定义线程池

2. 线程切换总结:

  1. PublishOn:它将上游信号传给下游,同时改变后续的操作符的执行所在线程,直到下一个publishOn出现在这个链上。
  2. SubscribeOn:作用于向上的订阅链,无论处于操作链的什么位置,他都会影响到源头的线程执行环境,但不会影响后续的publishOn

3.Webflux处理流程解析

        首先我们看一下SpringMvc的请求处理流程,当请求进来之后会进入到DispatcherServlet,DispatcherServlet会将请求转发给handlerMapper找到映射器,之后通过HandlerAdapter找到对应的handler处理请求,处理完之后会调用ViewResolver视图解析器对结果进行解析,然后通过View视图解析器进行渲染。在Webflux中也存在类似DispatcherServlet的存在,那就是DispatcherHandler。

 

        DispatcherHandler类中的核心方法是handle,该方法的参数是ServerWebExchange,该类的作用是Http请求和响应相互的纽带,该类中不仅提供了获取ServerHttpRequest和ServerHttpResponse,而且还为服务端处理请求时提供了相关的属性的方法,如获取request attribute、session等,handler处理的主要流程是先获取handlerMappings,然后调用concatMap方法获取对应的HandlerMapping,该方法是保证顺序的,如果在controller和RouterFunction同时存在相同的path,那么只会执行第一个,也就是routerFunction的handler,然后执行该方法并处理返回的结果。

        DispatcherHandler实现了ApplicationContextAware接口,在setApplicationContext方法中调用了initStrategies方法,该方法完成了DispatcherHandler的准备工作。

   该方法首先获取所有的HandlerMapping实现类,有三类,分别是requestMappingHandlerMapping主要处理SpringMvc注解方式;第二个是routerFunctionMapping,这个是实现RouterFunction接口,通过此种方式配置路径映射的关系;第三个是resourceHandlerMapping,其类型为SimpleUrlHandlerMapping,主要处理通过url匹配路径,如/webjars/**、/**相关的ResourceWebHandler。

        其次获取HandlerAdapter的实现类,Handler主要是根据@RequestMapping的注解配置的path找到对应的方法,然后执行此方法。 

        最后获取所有实现了HandlerResultHandler接口的子类,共有4种实现,ResponseEntityResultHandler主要处理HttpEntity和ResponseEntity;ResponseBodyResultHandler主要处理@ResponseBody标注的返回结果;ViewResolutionResultHandler主要处理返回值为void、String、View、Model、Map、Rendering和ModelAndView。 

        因此,RouterFucntion实现了InitilizationBean,所以先会调用afterPropertiesSet方法,整个初始化流程为:

至此,完成了Webflux的准备工作,那么接下来看下对请求的处理流程:

 

4.总结

        webFlux采用异步非阻塞模型,相比于SpringMvc可以极大的提升吞吐量。但是也不是没有副作用,像学习曲线高、调试难以及不支持jdbc等数据库,而NoSql数据库相对支持较为完善,而且它可以和SpringMvc一起使用。

        WebFlux采用reactor作为响应式编程框架。Reactor采用异步非阻塞式模型,而非同步命令式编程。

 

 

 

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐