Spring Boot 2.0
spring.io 官网有句醒目的话是:
BUILD ANYTHING WITH SPRING BOOT
Spring Boot (Boot 顾名思义,是引导的意思)框架是用于简化 Spring 应用从搭建到开发的过程。应用开箱即用,只要通过一个指令,包括命令行 java -jar 、SpringApplication 应用启动类 、 Spring Boot Maven 插件等,就可以启动应用了。另外,Spring Boot 强调只需要很少的配置文件,所以在开发生产级 Spring 应用中,让开发变得更加高效和简易。目前,Spring Boot 版本是 2.x 版本。Spring Boot 包括 WebFlux。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-z0QiBq9N-1647350877518)(//upload-images.jianshu.io/upload_images/13587608-2108800ca0602799.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)]
传统的以SpringMVC为代表的webmvc技术使用的是同步阻塞式IO模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-we3JkRy0-1647350877522)(//upload-images.jianshu.io/upload_images/13587608-e87cc1031dff253b.png?imageMogr2/auto-orient/strip|imageView2/2/w/891/format/webp)]
而Spring WebFlux是一个异步非阻塞式IO模型,可以用少量的容器线程支撑大量的并发访问,所以Spring WebFlux可以提升吞吐量和伸缩性,但是接口的响应时间并不会缩短,其处理结果还是得由worker线程处理完成之后在返回给请求。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉xin(同英):1253431195 扩列获取资料学习,无工作经验不要加哦!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rtkYH6rj-1647350877523)(//upload-images.jianshu.io/upload_images/13587608-0c9ab223c04faeb0.png?imageMogr2/auto-orient/strip|imageView2/2/w/1200/format/webp)]
适合IO密集型、磁盘IO密集、网络IO密集等服务场景,比如微服务网关,就可以使用webflux技术来显著的提升网关对下游服务的吞吐量,spring cloud gateway就使用了webflux这门技术
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o3urQyoN-1647350877524)(//upload-images.jianshu.io/upload_images/13587608-371f3ac43c0227b1.png?imageMogr2/auto-orient/strip|imageView2/2/w/861/format/webp)]
了解 WebFlux,首先了解下什么是 Reactive Streams。Reactive Streams 是 JVM 中面向流的库标准和规范:
背压是一种常用策略,使得发布者拥有无限制的缓冲区存储元素,用于确保发布者发布元素太快时,不会去压制订阅者。
一般由以下组成:
public interface Publisher {
void subscribe(Subscriber super T> var1);
}
public interface Subscriber {
void onSubscribe(Subscription var1);
void onNext(T var1);
void onError(Throwable var1);
void onComplete();
}
public interface Subscription {
void request(long var1);
void cancel();
}
public interface Processor extends Subscriber, Publisher {
}
有了 Reactive Streams 这种标准和规范,利用规范可以进行响应式编程。那再了解下什么是 Reactive programming 响应式编程。响应式编程是基于异步和事件驱动的非阻塞程序,只是垂直通过在 JVM 内启动少量线程扩展,而不是水平通过集群扩展。这就是一个编程范例,具体项目中如何体现呢?
响应式项目编程实战中,通过基于 Reactive Streams 规范实现的框架 Reactor 去实战。Reactor 一般提供两种响应式 API :
Spring Boot Webflux 就是基于 Reactor 实现的。Spring Boot 2.0 包括一个新的 spring-webflux 模块。该模块包含对响应式 HTTP 和 WebSocket 客户端的支持,以及对 REST,HTML 和 WebSocket 交互等程序的支持。一般来说,Spring MVC 用于同步处理,Spring Webflux 用于异步处理。
Spring Boot Webflux 有两种编程模型实现,一种类似 Spring MVC 注解方式,另一种是使用其功能性端点方式。
常用的 Spring Boot 2.0 WebFlux 生产的特性如下:
还有对日志、Web、消息、测试及扩展等支持。
Reactor 框架是 Spring Boot Webflux 响应库依赖,通过 Reactive Streams 并与其他响应库交互。提供了 两种响应式 API:Mono 和 Flux。一般是将 Publisher 作为输入,在框架内部转换成 Reactor 类型并处理逻辑,然后返回 Flux 或 Mono 作为输出。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉xin(同英):1253431195 扩列获取资料学习,无工作经验不要加哦!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ENh7FPTU-1647350877526)(//upload-images.jianshu.io/upload_images/13587608-bd7cea70050a4c66.png?imageMogr2/auto-orient/strip|imageView2/2/w/800/format/webp)]
一图就很明确了,WebFlux 和 MVC 有交集,方便大家迁移。但是注意:
Spring 5 web 模块包含了 Spring WebFlux 的 HTTP 抽象。类似 Servlet API , WebFlux 提供了 WebHandler API 去定义非阻塞 API 抽象接口。可以选择以下两种编程模型实现:
跟 Spring Boot 大框架一样启动应用,但 WebFlux 默认是通过 Netty 启动,并且自动设置了默认端口为 8080。另外还提供了对 Jetty、Undertow 等容器的支持。开发者自行在添加对应的容器 Starter 组件依赖,即可配置并使用对应内嵌容器实例。
但是要注意,必须是 Servlet 3.1+ 容器,如 Tomcat、Jetty;或者非 Servlet 容器,如 Netty 和 Undertow。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mRe8zuMb-1647350877527)(//upload-images.jianshu.io/upload_images/13587608-6439849871f5493c.png?imageMogr2/auto-orient/strip|imageView2/2/w/647/format/webp)]
Future局限
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Rs3Mqhos-1647350877528)(//upload-images.jianshu.io/upload_images/13587608-2635442505128957.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tuGMtq94-1647350877529)(//upload-images.jianshu.io/upload_images/13587608-dd24951492c7fe52.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NOt0wadI-1647350877530)(//upload-images.jianshu.io/upload_images/13587608-24769a4237bf39c0.png?imageMogr2/auto-orient/strip|imageView2/2/w/1123/format/webp)]
org.springframework.boot
spring-boot-starter-webflux
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
@Test
public void testReactor(){
Flux flux = Flux.just(1, 2, 3, 4, 5, 6);
Mono mono = Mono.just(1);
Integer[] arr = {1,2,3,4,5,6};
Flux flux1 = Flux.fromArray(arr);
List list = Arrays.asList(1, 2, 3, 4, 5, 6);
Flux flux2 = Flux.fromIterable(list);
Flux flux3 = Flux.from(flux);
Flux flux4 = Flux.fromStream(Stream.of(1, 2, 3, 4, 5, 6));
flux.subscribe();
flux1.subscribe(System.out::println);
flux2.subscribe(System.out::println,System.err::println);
flux3.subscribe(System.out::println,System.err::println,() -> System.out.println("complete"));
flux4.subscribe(System.out::println,System.err::println,
() -> System.out.println("complete"),
subscription -> subscription.request(3));
flux4.subscribe(new DemoSubscriber());
}
class DemoSubscriber extends BaseSubscriber{
@Override
protected void hookOnSubscribe(Subscription subscription) {
System.out.println("Subscribe");
subscription.request(1);
}
@Override
protected void hookOnNext(Integer value) {
if(value == 4){
//背压,通知数据源,不要发送数据了
cancel();
}
System.out.println(value);
request(1);
}
}
}
map操作可以将数据元素进行转换/映射,得到一个新元素。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7mIXxVVZ-1647350877531)(//upload-images.jianshu.io/upload_images/13587608-368b8ab8b5a692cd.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
flatMap操作可以将每个数据元素转换/映射为一个流,然后将这些流合并为一个大的数据流。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nGHXbvoO-1647350877532)(//upload-images.jianshu.io/upload_images/13587608-cdfb29dbd34ffe8f.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
filter操作可以对数据元素进行筛选。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Vdv4loSy-1647350877532)(//upload-images.jianshu.io/upload_images/13587608-033ebaeee6d17642.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
看到zip这个词可能会联想到拉链,它能够将多个流一对一的合并起来。zip有多个方法变体,我们介绍一个最常见的二合一的。想学习交流HashMap,nginx、dubbo、Spring MVC,分布式、高性能高可用、MySQL,redis、jvm、多线程、netty、kafka、的加尉xin(同英):1253431195 扩列获取资料学习,无工作经验不要加哦!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-45QXlchE-1647350877533)(//upload-images.jianshu.io/upload_images/13587608-84fafc95687bd6ca.png?imageMogr2/auto-orient/strip|imageView2/2/w/640/format/webp)]
Reactor中提供了非常丰富的操作符,除了以上几个常见的,还有:
create
和generate
等及其变体方法;doOnNext
、doOnError
、doOncomplete
、doOnSubscribe
、doOnCancel
等及其变体方法;when
、and/or
、merge
、concat
、collect
、count
、repeat
等及其变体方法;take
、first
、last
、sample
、skip
、limitRequest
等及其变体方法;timeout
、onErrorReturn
、onErrorResume
、doFinally
、retryWhen
等及其变体方法;window
、buffer
、group
等及其变体方法;publishOn
和subscribeOn
方法。使用这些操作符,你几乎可以搭建出能够进行任何业务需求的数据处理管道/流水线。
抱歉以上这些暂时不能一一介绍,更多详情请参考JavaDoc
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OoFgSIEN-1647350877533)(//upload-images.jianshu.io/upload_images/13587608-b39ed01cd59ba6e1.png?imageMogr2/auto-orient/strip|imageView2/2/w/1172/format/webp)]
@RunWith(SpringRunner.class)
@SpringBootTest
public class ApplicationTest {
@Test
public void testReactor() throws InterruptedException {
Flux flux = Flux.just(1, 2, 3, 4, 5, 6);
flux.map(i -> {
System.out.println(Thread.currentThread().getName()+"-map1");
return i * 3;
}).publishOn(Schedulers.elastic()).map(
i -> {
System.out.println(Thread.currentThread().getName()+"-map2");
return i / 3;
}
).subscribeOn(Schedulers.parallel())
.subscribe(i -> System.out.println(Thread.currentThread().getName()+"-" + i));
Thread.sleep(10000);
}
}