java处理异步非阻塞请求_Spring WebFlux 的异步非阻塞处理
前言
随着 Web Servlet 技术栈的不断发展实现了异步处理与非阻塞 IO,但是其异步是不彻底的,因为受制于 Servlet 规范本身,比如其规范是同步的(Filter,Servlet)或阻塞(getParameter,getPart)。
所以新的使用少量线程和较少的硬件资源来处理并发的非阻塞 Web 技术栈应运而生- WebFlux,其是与 Servlet 技术栈并行存在的一种新的技术,其基于 JDK8 函数式编程与 Netty 实现天然的异步、非阻塞处理。
本 Chat 则主要讲解 Spring 框架 5.0 中引入的新的 WebFlux 技术栈,内容如下:
WebFlux 存在的价值与意义是什么
WebFlux 的并发模型是怎样的
WebFlux 的的两种编程模型是怎样的
如何使用 WebFlux 进行编程
WebFlux 内部实现原理是怎么样的
WebFlux 的适用场景是什么
Spring WebFlux 概述
Spring 框架中包含的原始 Web 框架 Spring Web MVC 是专为 Servlet API 和 Servlet 容器构建的。反应式栈的 Web 框架 Spring WebFlux 则是在 Spring 5.0 版中才新添加的,它是完全无阻塞的,并且支持 Reactive Streams 回压,并可以在 Netty 、Undertow 和 Servlet 3.1+容器等服务器上运行,其中 WebFlux 中的 Flux 是源自 Reactor 库中的 Flux 流对象。如下图左侧是 spring-webmvc 模块提供的传统的基于 Servlet 的 Spring MVC 技术栈,右侧是 spring-webflux 模块的反应式编程技术栈(reactive stack)。
Web 技术栈对比
Servlet API 最初是为了通过 Filter->Servlet 链进行单次传递而构建的。 Servlet 3.0 规范中添加的异步请求处理允许应用程序及时退出 Filter-Servlet 链(及时释放容器线程),但保持响应打开以便异步线程进行后续处理。 Spring MVC 的异步处理支持是围绕该机制构建的。当 controller 返回 DeferredResult 时,将退出 Filter-Servlet 链,并释放 Servlet 容器线程。稍后,当设置 DeferredResult 时,会对请求进行重新分派,使用 DeferredResult 值(就像 controller 返回它一样)以恢复处理。
相比之下,Spring WebFlux 既不是基于 Servlet API 构建的,也不需要这样的异步请求处理功能,因为它在设计上是异步的。其对异步的处理是内置于框架规范中的,并通过请求处理的所有阶段进行内在支持。
从编程模型的角度来看,Spring MVC 和 Spring WebFlux 都支持异步和反应式作为 controller 方法中的返回值。 Spring MVC 甚至支持流媒体,包括反应性回压功能,但是其对响应的写入仍然是阻塞的(并且在单独的线程上执行), Servlet 3.1 确实为非阻塞 I / O 提供了 API,但是使用它会远离 Servlet API 的其余部分,比如其规范是同步的(Filter,Servlet)或阻塞的(getParameter,getPart)。WebFlux 则不同,其依赖于非阻塞 I / O,并且每次写入都不需要额外的线程进行支持。
Reactive 编程 & Reactor 库
术语 Reactive(反应式编程),其是指围绕变化做出反应的编程模型 - 比如对 I / O 事件做出反应的网络组件,对鼠标事件做出反应的 UI 控制器等。从这个意义上说,非阻塞是被动的,因为我们现在处于一种模式,即在操作完成或数据可用时对结果作出反应。
Reactive Streams 是一个规范(在 Java 9 中也采用),用于定义具有回压的异步组件之间的交互。例如,数据存储库(充当发布者)可以产生数据(从数据库迭代出数据),然后 HTTP 服务器(充当订阅服务器)可以把迭代出的数据写入请求响应中,那么从数据库里面迭代数据的快慢就取决于 HTTP 服务器向响应对象里面写入的快慢。 Reactive Streams 的主要目的是让订阅者控制发布者生成数据的速度。
另外 Reactive Streams 的目的是建立回压的一种机制和一个边界限制,如果发布者不能够降低自己生产数据的速度,那么它要决定是否要缓存或者丢失或者报错失败。
Reactive Streams 在互操作性方面发挥着重要作用。它对库和基础架构组件很有用,但作为应用程序 API 不太有用,因为它太低级了。应用程序需要更高级别和更丰富的功能 API 来组成异步逻辑 - 类似于 Java 8 Stream API,但其不仅适用于集合。这是 Reactive 库所扮演的角色,Java 中已有的 Reactive 库有 Reactor 和 RxJava,Spring 团队认为 Reactor 是 Spring WebFlux 的首选 reactive 库。Reactor 提供 Mono 和 Flux API 流类型,其提供了与 ReactiveX 词汇表对齐的丰富运算符,处理 0..1(Mono)和 0..N(Flux)的数据序列。 Reactor 是一个 Reactive Streams 库,因此它的所有运营商都支持非阻塞反压功能,它是与 Spring 密切合作开发的。
WebFlux 要求 Reactor 作为核心依赖,但它可以通过 Reactive Streams 与其他反应式库互(比如 RxJava)交互操作。作为一般规则,WebFlux API 接受普通 Publisher 作为输入,在内部使其适配 Reactor 类型,使用它并返回 Flux 或 Mono 作为输出。因此,您可以将任何 Publisher 作为输入传递,并且可以对输出应用操作符,但是您需要调整输出以与其他类型的反应库(例如 RxJava)一起使用。只要可行(例如带注解的 controller),WebFlux 就会透明地适配 RxJava 或其他反应库的使用。
WebFlux 服务器
Spring WebFlux 可以在 Tomcat、Jetty、Servlet 3.1+容器以及非 Servlet 运行时(如 Netty 和 Undertow)上运行。所有服务器都适用于低级别的通用 API,因此可以跨服务器支持更高级别的编程模型。
java处理异步非阻塞请求_Spring WebFlux 的异步非阻塞处理相关推荐
- 嵌入式软件异步编程:请求的多阶段异步处理
本文节选自<深入理解Nginx模块开发与架构解析(第2版)>第8章 Nginx基础架构 >> 8.2Nginx的架构设计 >> 8.2.3 请求的多阶段异步处理,和 ...
- flask异步操作_Flask实现异步非阻塞请求功能实例解析
本文研究的主要是Flask实现异步非阻塞请求功能,具体实现如下. 最近做物联网项目的时候需要搭建一个异步非阻塞的HTTP服务器,经过查找资料,发现可以使用gevent包. 关于gevent Geven ...
- Spring WebFlux 的异步非阻塞处理
虽然 Web Servlet 技术栈的不断发展实现了异步处理与非阻塞 IO,但是其异步是不彻底的,因为受制于 Servlet 规范本身,比如其规范是同步的(Filter,Servlet)或阻塞(get ...
- 【C/C++服务器开发】同步与异步、阻塞与非阻塞、同步调用和异步调用的概念
同步与异步 首先我们要明确的是,同步和异步都是针对两个或者两个以上的事物来说的.比如当我们在网上购物看中一件物品,然后去浏览该商品详情的时候,首先页面会先发送一个请求,后台服务器查询对应商品的相关数据 ...
- php协程实现mysql异步_swoole与php协程实现异步非阻塞IO开发
"协程可以在遇到阻塞的时候中断主动让渡资源,调度程序选择其他的协程运行.从而实现非阻塞IO" 然而php是不支持原生协程的,遇到阻塞时如不交由异步进程来执行是没有任何意义的,代码还 ...
- java非阻塞锁_Java并发问题的非阻塞解决方案
转自http://blog.csdn.net/u011277203/article/details/9223545 在并发环境中,对于共享资源通常会采用显式的锁机制(比如synchronized或Re ...
- cpu 被挂起和阻塞_迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章...
网上有很多讲同步/异步/阻塞/非阻塞/BIO/NIO/AIO的文章,但是都没有达到我的心里预期,于是自己写一篇出来. 常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数 ...
- 异步就是异步,根本就没有 异步非阻塞IO这个说法。阻塞 非阻塞,同步I/O 异步I/O 的区别
先给大家安利一下这个 https://www.ibm.com/developerworks/cn/linux/l-async/ 里面关于 异步非阻塞IO 是错的. 异步就是异步,别扯 异步阻塞 异步非 ...
- JAVA基础知识之网络编程——-基于AIO的异步Socket通信
异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...
最新文章
- Linux基础(二)--基础的命令ls和date的详细用法
- python批量命名变量_python变量命名的7条建议
- Nginx http keepalive提升链接效率
- 2.6 datetime 模块
- 3d数学基础图形与游戏开发 英文版_1850款文字标题字幕条,AE图形预设包,logo生成神器...
- [COCI2017-2018#5] Karte
- python实现猴子爬山算法
- 一个能支持Flash的广告控件
- 我用VS2015 开发webapp (1) 需求、目的、配置
- (转)Windows Phone7页面导航
- HTML与JSP页面的区别
- ThinkPad工程师回答
- foobar2000在线标签服务器,不再烦恼 小烧友手把手教你设置 Foobar2000界面
- PCHunter_32X64_2022_03最新版
- 什么是转义字符?转义字符有哪些?为什么使用转义字符?
- Qt常用UI控件读取、写入方法
- 织梦dede源码列表页调用tags标签并带链接的实现方法
- 四个核心技术构成智能语音系统
- Docker11_1:Docker阿里云仓库
- 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
热门文章
- 通过AppStore上的app生成二维码扫描下载
- 小团队如何设计一款“高流水”的数值类Roguelike
- [微软编程之美挑战赛P2]女神---CLJ神犇的代码
- Qt中接收串口数据不完整、分段的解决方法
- Cesium功能实现(一)创建billboard广告牌
- JavaScript中对象(Object)的方法
- InsecurePlatformWarning:真正的SSLContext对象不可用。这可以防止urllib3适当地配置SSL [重复]
- An动画优化之传统引导层动画
- 苹果4s忘记id密码怎么办_大哭!iPhone手机ID密码忘记了怎么办?3种方法轻松解决问题...
- 线性布局嵌套相对布局