前言

随着 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 的异步非阻塞处理相关推荐

  1. 嵌入式软件异步编程:请求的多阶段异步处理

    本文节选自<深入理解Nginx模块开发与架构解析(第2版)>第8章 Nginx基础架构 >> 8.2Nginx的架构设计 >> 8.2.3 请求的多阶段异步处理,和 ...

  2. flask异步操作_Flask实现异步非阻塞请求功能实例解析

    本文研究的主要是Flask实现异步非阻塞请求功能,具体实现如下. 最近做物联网项目的时候需要搭建一个异步非阻塞的HTTP服务器,经过查找资料,发现可以使用gevent包. 关于gevent Geven ...

  3. Spring WebFlux 的异步非阻塞处理

    虽然 Web Servlet 技术栈的不断发展实现了异步处理与非阻塞 IO,但是其异步是不彻底的,因为受制于 Servlet 规范本身,比如其规范是同步的(Filter,Servlet)或阻塞(get ...

  4. 【C/C++服务器开发】同步与异步、阻塞与非阻塞、同步调用和异步调用的概念

    同步与异步 首先我们要明确的是,同步和异步都是针对两个或者两个以上的事物来说的.比如当我们在网上购物看中一件物品,然后去浏览该商品详情的时候,首先页面会先发送一个请求,后台服务器查询对应商品的相关数据 ...

  5. php协程实现mysql异步_swoole与php协程实现异步非阻塞IO开发

    "协程可以在遇到阻塞的时候中断主动让渡资源,调度程序选择其他的协程运行.从而实现非阻塞IO" 然而php是不支持原生协程的,遇到阻塞时如不交由异步进程来执行是没有任何意义的,代码还 ...

  6. java非阻塞锁_Java并发问题的非阻塞解决方案

    转自http://blog.csdn.net/u011277203/article/details/9223545 在并发环境中,对于共享资源通常会采用显式的锁机制(比如synchronized或Re ...

  7. cpu 被挂起和阻塞_迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章...

    网上有很多讲同步/异步/阻塞/非阻塞/BIO/NIO/AIO的文章,但是都没有达到我的心里预期,于是自己写一篇出来. 常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数 ...

  8. 异步就是异步,根本就没有 异步非阻塞IO这个说法。阻塞 非阻塞,同步I/O 异步I/O 的区别

    先给大家安利一下这个 https://www.ibm.com/developerworks/cn/linux/l-async/ 里面关于 异步非阻塞IO 是错的. 异步就是异步,别扯 异步阻塞 异步非 ...

  9. JAVA基础知识之网络编程——-基于AIO的异步Socket通信

    异步IO 下面摘子李刚的<疯狂JAVA讲义> 按照POSIX标准来划分IO,分为同步IO和异步IO.对于IO操作分为两步,1)程序发出IO请求. 2)完成实际的IO操作. 阻塞IO和非阻塞 ...

最新文章

  1. Linux基础(二)--基础的命令ls和date的详细用法
  2. python批量命名变量_python变量命名的7条建议
  3. Nginx http keepalive提升链接效率
  4. 2.6 datetime 模块
  5. 3d数学基础图形与游戏开发 英文版_1850款文字标题字幕条,AE图形预设包,logo生成神器...
  6. [COCI2017-2018#5] Karte
  7. python实现猴子爬山算法
  8. 一个能支持Flash的广告控件
  9. 我用VS2015 开发webapp (1) 需求、目的、配置
  10. (转)Windows Phone7页面导航
  11. HTML与JSP页面的区别
  12. ThinkPad工程师回答
  13. foobar2000在线标签服务器,不再烦恼 小烧友手把手教你设置 Foobar2000界面
  14. PCHunter_32X64_2022_03最新版
  15. 什么是转义字符?转义字符有哪些?为什么使用转义字符?
  16. Qt常用UI控件读取、写入方法
  17. 织梦dede源码列表页调用tags标签并带链接的实现方法
  18. 四个核心技术构成智能语音系统
  19. Docker11_1:Docker阿里云仓库
  20. 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...

热门文章

  1. 通过AppStore上的app生成二维码扫描下载
  2. 小团队如何设计一款“高流水”的数值类Roguelike
  3. [微软编程之美挑战赛P2]女神---CLJ神犇的代码
  4. Qt中接收串口数据不完整、分段的解决方法
  5. Cesium功能实现(一)创建billboard广告牌
  6. JavaScript中对象(Object)的方法
  7. InsecurePlatformWarning:真正的SSLContext对象不可用。这可以防止urllib3适当地配置SSL [重复]
  8. An动画优化之传统引导层动画
  9. 苹果4s忘记id密码怎么办_大哭!iPhone手机ID密码忘记了怎么办?3种方法轻松解决问题...
  10. 线性布局嵌套相对布局