Spring webflux--响应式、非阻塞、事件驱型web框架

一、基本概念:

在进行网络编程时,我们常常见到同步(Synchronous I/O)/异步(Asynchronous I/O),阻塞(Blocking I/O)/非阻塞(Non-blocking I/O)四种调用方式,下面将这几个基本概念解释一下:

1. 同步/异步:【主要针对C端】

所谓同步,就是在C端发出一个功能调用时,在没有得到结果之前,该调用就不返回。也就是必须一件一件事做,等前一件做完了才能做下一件事。

例如普通B/S模式(同步):提交请求--->等待服务器处理--->处理完毕返回。 整个期间客户端浏览器不能干任何事。

而异步的概念和同步相对,当C端一个异步过程调用发起后,调用者不能立刻得到结果。实际处理这个调用的部件在完成后,通过状态、通知和回调来通知调用者。

例如:ajax请求(异步):请求通过事件触发--->服务器处理(这是浏览器仍然可以作其他事情)--->处理完毕。

2. 阻塞/非阻塞:【主要针对S端】

阻塞调用是指调用结果返回之前,当前线程会被挂起(线程进入非可执行状态,在这个状态下,cpu不会给线程分配时间片,即线程暂停运行)。函数只有在得到结果之后才会返回。

有人也许会把阻塞调用和同步调用等同起来,实际上他是不同的。对于同步调用来说,很多时候当前线程还是**的,只是从逻辑上当前函数没有返回而已。 例如,我们在socket中调用recv函数,如果缓冲区中没有数据,这个函数就会一直等待,直到有数据才返回。而此时,当前线程还会继续处理各种各样的消息。

快递的例子:比如到你某个时候到A楼一层(假如是内核缓冲区)取快递,但是你不知道快递什么时候过来,你又不能干别的事,只能死等着。但你可以睡觉(进程处于休眠状态),因为你知道快递把货送来时一定会给你打个电话(假定一定能叫醒你)。

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

还是等快递的例子:如果用忙轮询的方法,每隔5分钟到A楼一层(内核缓冲区)去看快递来了没有。如果没来,立即返回。而快递来了,就放在A楼一层,等你去取。

Spring Web MVC ,Spring Web MVC 是基于 Servlet API 和 Servlet 容器设计的。那么 Spring WebFlux 肯定不是基于前面两者,它基于 Reactive Streams API 和 Servlet 3.1+ 容器设计。

1. 那Reactive Streams API

先理解 Stream 流是什么?流是序列,是生产者生产,一个或多个消费者消费的元素序列。这种具体的设计模式成为发布订阅模式。常见的流处理机制是 pull / push 模式。背压是一种常用策略,使得发布者拥有无限制的缓冲区存储 item,用于确保发布者发布 item 太快时,不会去压制订阅者。
Reactive Streams (响应式流)是提供处理非阻塞背压异步流的一种标准。主要针对的场景是运行时环境(包括 JVM 和 JS)和网络。同样,JDK 9 java.util.concurrent 包提供了两个主要的 API 来处理响应流:
- Flow
- SubmissionPublisher

2.为啥只能运行在 Servlet 3.1+ 容器?

大家知道,3.1 规范其中一个新特性是异步处理支持。
异步处理支持:Servlet 线程不需一直阻塞,即不需要到业务处理完毕再输出响应,然后结束 Servlet线程。异步处理的作用是在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,在不生成响应的情况下返回至容器。主要应用场景是针对业务处理较耗时的情况,可以减少服务器资源的占用,并且提高并发处理速度。
所以 WebFlux 支持的容器有 Tomcat、Jetty(Non-Blocking IO API) ,也可以像 Netty 和 Undertow 的本身就支持异步容器。在容器中 Spring WebFlux 会将输入流适配成 Mono 或者 Flux 格式进行统一处理。

二、响应式宣言

不知道是不是为了向敏捷宣言致敬,响应式宣言中也包含了4组关键词:

  • Responsive: 可响应的。要求系统尽可能做到在任何时候都能及时响应。

  • Resilient: 可恢复的。要求系统即使出错了,也能保持可响应性。

  • Elastic: 可伸缩的。要求系统在各种负载下都能保持可响应性。

  • Message Driven: 消息驱动的。要求系统通过异步消息连接各个组件。

可以看到,对于任何一个响应式系统,首先要保证的就是可响应性,否则就称不上是响应式系统。从这个意义上来说,动不动就蓝屏的Windows系统显然不是一个响应式系统。

左侧是传统的基于Servlet的Spring Web MVC框架,右侧是5.0版本新引入的基于Reactive Streams的Spring WebFlux框架,从上到下依次是Router Functions,WebFlux,Reactive Streams三个新组件。

  • Router Functions: 对标@Controller,@RequestMapping等标准的Spring MVC注解,提供一套函数式风格的API,用于创建Router,Handler和Filter。

  • WebFlux: 核心组件,协调上下游各个组件提供响应式编程支持。

  • Reactive Streams: 一种支持背压(Backpressure)的异步数据流处理标准,主流实现有RxJava和Reactor,Spring WebFlux默认集成的是Reactor。

在Web容器的选择上,Spring WebFlux既支持像Tomcat,Jetty这样的的传统容器(前提是支持Servlet 3.1 Non-Blocking IO API),又支持像Netty,Undertow那样的异步容器。不管是何种容器,Spring WebFlux都会将其输入输出流适配成Flux<DataBuffer>格式,以便进行统一处理。

值得一提的是,除了新的Router Functions接口,Spring WebFlux同时支持使用老的Spring MVC注解声明Reactive Controller。和传统的MVC Controller不同,Reactive Controller操作的是非阻塞的ServerHttpRequest和ServerHttpResponse,而不再是Spring MVC里的HttpServletRequest和HttpServletResponse。

三、Spring 5 - Spring webflux

它是一个新的非堵塞函数式 Reactive Web 框架,可以用来建立异步的,非阻塞,事件驱动的服务,并且扩展性非常好。把阻塞(不可避免的)风格的代码迁移到函数式的非阻塞 Reactive 风格代码。

  • 新的spring-webflux模块,一个基于reactive的spring-webmvc,完全的异步非阻塞,旨在使用enent-loop执行模型和传统的线程池模型。

  • Reactive说明在spring-core比如编码和解码

  • spring-core相关的基础设施,比如Encode 和Decoder可以用来编码和解码数据流;DataBuffer 可以使用java ByteBuffer或者Netty ByteBuf;ReactiveAdapterRegistry可以对相关的库提供传输层支持。

  • 在spring-web包里包含HttpMessageReade和HttpMessageWrite



将不定期更新资源,欢迎持续关注

想获得更多的学习知识请关注微信公众号:西北码农或扫下方二维码

来源:https://yq.aliyun.com/articles/673146


智能推荐

响应式Spring的道法术器(Spring WebFlux 快速上手 + 全面介绍)

1. Spring WebFlux 2小时快速入门 Spring 5 之使用Spring WebFlux开发响应式应用。 lambda与函数式(15min) Reactor 3 响应式编程库(60min) Spring Webflux和Spring Data Reactive开发响应式应用(45min) 通过以上内容相信可以对Spring 5.0 推出的响应式开发有了初步的体会。如果希望有更加深入...

Spring框架 - Spring概述

为什么80%的码农都做不了架构师?>>>    #Spring概述 ##Spring框架是什么? Spring Framework轻量级、一站式、开发框架 轻量级是指相对于老的J2EE当中的EJB 一站式是指集成了很多的各种开发工具,提供数据访问,Web开发工具,整合了数据访问、Web开发的一些框架。例如Hibernate、 ##Spring历史 2002 -...

Spring 事件

Spring的事件处理需要遵循如下流程: 自定义事件,定义的事件继承ApplicationEvent抽象类 定义事件的监听器,实现ApplicationListener接口 使用ApplicationContext容器发布事件。 这里的流程涉及到三个组件:ApplicationEvent、ApplicationListener和ApplicationContext。 其中,接口 Applicati...

spring事件

导入mavenjar: <dependency>  <groupId>org.aspectj</groupId>  <artifactId>aspectjweaver</artifactId>  <version>1.6.4</version> </dependency>...

DOS,DDOS的区别通俗讲+DDOS应用场景

DOS,DDOS的区别通俗讲+DDOS应用场景 博主是刚入行的新手,最近在研究异常漏洞数据的检测,这里看了好多篇论文和博客我才总算是比较通俗一点的理解了各种漏洞的特性应用场景,这次就先简单的讲解一下DDOS。 本文分成两大板块,首先来区分一下DOS和DDOS和特性和区别,(参考了公众号:黄庆龙 网络工程师阿龙 还有黑客帝国)再来主要讲解一下实际场景中我们经常遇到的DDOS的特性的行为(参考了:科来...

猜你喜欢

对《视觉SLAM十四讲》4.3.5节李代数求导的推导过程的勘误

一、引言 在《视觉SLAM十四讲》(1)的4.3.5节,推导了李代数求导的表达式,我认为其中存在一些容易产生歧义的符号使用,本文先展示我认为正确的推导,然后提出了修改建议。 二、正确推导过程 我们假设旋转并且微扰后的位姿是一个关于 ϵ \boldsymbol\epsilon ϵ和 ξ \boldsymbol\xi ξ的多元函数 f ( ϵ , ξ ) f(\boldsymbol\...

磁盘配额 | 物理卷pv 逻辑卷组vg LVM | 扩大LVM xfs类型 | 扩大缩小ext4类型 | 移除闲置设备 | 给文件做快照 | 查看LVM信息 |删除LVM |

注意:挂载设备之后设备挂载点的权限和未挂载时的权限是不一样的,处在哪个状态,修改谁的就显示谁的 一,磁盘配额 1,fdisk /dev/vdb 分100M给vdb1 2,给/mnt 777的权限(此时不要挂载设备,否则权限是给设备的,而不是给/mnt这个目录的)      然后要格式化磁盘否则会报错mount: unknown filesystem type...

JVM总结

JVM总体结构 运行过程 Java源文件-编译器-字节码文件 字节码文件-JVM-机器码 JVM内存区域 JVM运行时内存 Java堆从GC的角度可以细分为:新生代(Eden区,From Survivor区和To Survivor区)和老年代 Eden区 Java新对象的出生地,当Eden区内存不够时,会触发MinorGC,对新生代区进行一次垃圾回收 SurvivorFrom 上一次GC的幸存者,...

js逆向 混淆加密反调试分析学习

学习文章:https://blog.csdn.net/qq_18421167/article/details/100574947 网站:aHR0cCUzQS8veXMuZmdqLnRhaXl1YW4uZ292LmNuL0ZpcnN0aGFuZC90eWZjL3B1Ymxpc2gvcC9Qcm9qZWN0TGlzdC5kbw== 1.要分析加密的数据 2.断点调试【打印可变参数和结果】 有2个deb...

8、文件、目录与操作

本专栏面向初中级用户。 充分考虑到初学者的实际需求,摒弃了一些艰深的计算机专业术语及对一些较为复杂的技术细节的介绍,通过大量实用的操作指导和具有代表性的实例,由浅入深、循序渐进的进行讲解,带领大家快速、直观的学习Linux操作系统的使用方法,掌握Linux系统管理的方法。 一、文件介绍 广义:一切皆文件 狭义:磁盘文件 Linux中文件是一个字符流序列: 普通文件(文本文件、可执行文件) 目录 磁...

问答精选

How to set a listener on array of checkboxes in jQuery?

Situation: Trying to 'collect' all checkboxes with this: And that works. Now I just want to make an action if any of these checkboxes is changed like this; But in console I get this: This is the whole...

Next js: Error: Objects are not valid as a React child (found: Error: Response not successful: Received status code 401)

This app shows Github issues with graphql API. I didn't change anything after finishing the app but I got this error. I used Next js, Typescript, Material UI, Tailwind css and GraphQL for this project...

Making tracebacks clickable when running Python unit tests inside Sublime Text

Is it possible to make output clickable: clicking the traceback line takes you to the corresponding Python file in Sublime Text edit tab? PythonTraceback plugin makes it easier to navigate in python e...

Literal whitespace characters causing pattern to fail (sometimes)

I have this RegEx from my previous question. The problem is that sometimes it works, Sometimes it doesn't. I tried pasting it on an online simulator and got this: https://regex101.com/r/I3tnY4/3 The t...

Doctrine2: Warning: Illegal offset type in isset or empty

I've a ManyToMany relation in Listing entity: Somewhere in the ListingService I'm trying to remove AttributeDescription from the Listing entity like this: But got an error: Warning: Illegal offset typ...

相关问题

相关文章

热门文章

推荐文章

相关标签

推荐问答