Spring5.0WebFlux⼊门及实战⽰例
什么是 Spring WebFlux
WebFlux是Spring推出响应式编程的⼀部分(web端)
响应式编程是异步⾮阻塞的(是⼀种基于数据流(data stream)和变化传递(propagation of change)的声明式(declarative)的编程范式)
Spring MVC 构建于 Servlet API 之上,使⽤的是同步阻塞式 I/O 模型,什么是同步阻塞式 I/O 模型呢?就是说,每⼀个请求对应⼀个线程去处理。
Spring WebFlux 是⼀个异步⾮阻塞式的 Web 框架,它能够充分利⽤多核 CPU 的硬件资源去处理⼤量的并发请求。
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 不是 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!
咱不能为了⽽,为了技术⽽技术,还要考量到转向⾮阻塞响应式编程学习曲线是陡峭的,⼩组成员的学习成本等诸多因素。
总之⼀句话,在合适的场景中,选型最合适的技术。
注意点
Spring MVC 因为是使⽤的同步阻塞式,更⽅便开发⼈员编写功能代码,Debug 测试等,⼀般来说,如果 Spring MVC 能够满⾜的场景,就尽量不要⽤ WebFlux;
WebFlux 默认情况下使⽤ Netty 作为服务器;
WebFlux 不⽀持 MySql;
⼊门WebFlux⽰例
maven依赖包
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
下⾯我们来看⼀个简单的例⼦(基于WebFlux环境构建):
// 阻塞5秒钟
private String createStr(){
try{
TimeUnit.SECONDS.sleep(5);
}catch(InterruptedException e){
}
return"some string";
}
// 普通的SpringMVC⽅法
@GetMapping("/1")
private String get1(){
log.info("get1 start");
String result =createStr();
log.info("get1 end.");
return result;
}
// WebFlux(返回的是Mono)spring mvc和boot区别
@GetMapping("/2")
private Mono<String>get2(){
log.info("get2 start");
Mono<String> result = Mono.fromSupplier(()->createStr());
log.info("get2 end.");
return result;
}
我们分别来访问⼀下SpringMVC的接⼝和WebFlux的接⼝,看⼀下有什么区别:
SpringMVC:
WebFlux:
从调⽤者(浏览器)的⾓度⽽⾔,是感知不到有什么变化的,因为都是得等待5s才返回数据。但是,从服务端的⽇志我们可以看出,WebFlux 是直接返回Mono对象的(⽽不是像SpringMVC⼀直同步阻塞5s,线程才返回)。
这正是WebFlux的好处:能够以固定的线程来处理⾼并发(充分发挥机器的性能)。
WebFlux还⽀持服务器推送(SSE - >Server Send Event),我们来看个例⼦:
/**
* Flux : 返回0-n个元素
* 注:需要指定MediaType
* @return
*/
@GetMapping(value ="/3", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
private Flux<String>flux(){
Flux<String> result = Flux
.fromStream(IntStream.range(1,5).mapToObj(i ->{
try{
TimeUnit.SECONDS.sleep(1);
}catch(InterruptedException e){
}
return"flux data--"+ i;
}));
return result;
}
效果就是每秒会给浏览器推送数据:
Reference

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。