1 什么是响应式编程

一句话总结:响应式编程是一种编程范式,通用和专注于数据流和变化的,并且是异步的。

维基百科原文

In computing, reactive programming is an asynchronous programming paradigm concerned with data streams and the propagation of change. This means that it becomes possible to express static (e.g. arrays) or dynamic (e.g. event emitters) data streams with ease via the employed programming language(s), and that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the change involved with data flow.

翻译

在计算机领域,响应式编程是一个专注于数据流和变化传递的**异步编程范式。**这意味着可以使用编程语言很容易地表示静态(例如数组)或动态(例如事件发射器)数据流,并且在关联的执行模型中,存在着可推断的依赖关系,这个关系的存在有利于自动传播与数据流有关的更改。

举例

例如,在命令式编程环境中, a:=b+c 表示将表达式的结果赋给a ,而之后改变b 或c 的值不会影响 。但在响应式编程中,a的值会随着b或c 的更新而更新。电子表格程序就是响应式编程的一个例子。单元格可以包含字面值或类似"=B1+C1"的公式,而包含公式的单元格的值会依据其他单元格的值的变化而变化 。

响应式编程最初是为了简化交互式用户界面的创建和实时系统动画的绘制而提出来的一种方法,但它本质上是一种通用的编程范式。

2 回顾Reactor

2.1 什么是Reactor

还是维基百科

The reactor design pattern is an event handling pattern for handling service requests delivered concurrently to a service handler by one or more inputs. The service handler then demultiplexes the incoming requests and dispatches them synchronously to the associated request handlers.

翻译

反应器(reactor)设计模式是一种事件处理模式,用于处理由一个或多个输入并发交付给服务处理程序的服务请求。然后,服务处理程序将传入的请求解复用,并将它们同步地分派给相关的请求处理程序。

2.2 为什么是Reactor

Reactor来源于网络IO中同步非阻塞的I/O多路复用机制的模式。

  • 堵塞、非堵塞的区别是在于第一阶段,即数据准备阶段。无论是堵塞还是非堵塞,都是用应用主动找内核要数据,而read数据的过程是‘堵塞’的,直到数据读取完。
  • 同步、异步的区别在于第二阶段,若由请求者主动的去获取数据,则为同步操作,需要说明的是:read/write操作也是‘堵塞’的,直到数据读取完。
    若数据的read都由kernel内核完成了(在内核read数据的过程中,应用进程依旧可以执行其他的任务),这就是异步操作。

换句话说,

  • BIO里用户最关心“我要读”,
  • NIO里用户最关心"我可以读了",
  • 在AIO模型里用户更需要关注的是“读完了”。

NIO一个重要的特点是:socket主要的读、写、注册和接收函数,在等待就绪阶段都是非阻塞的,真正的I/O操作是同步阻塞的(消耗CPU但性能非常高)。
NIO是一种同步非阻塞的I/O模型,也是I/O多路复用的基础。

Reactor模式基本结构:

  • Handle:本质上表示一种资源(比如说文件描述符,或是针对网络编程中的socket描述符),是由操作系统提供的;该资源用于表示一个个的事件,事件既可以来自于外部,也可以来自于内部,Handle是事件产生的发源地。
  • Synchronous Event Demultiplexer(同步事件分离器):它本身是一个系统调用,用于等待事件的发生(事件可能是一个,也可能是多个)。调用方在调用它的时候会被阻塞,一直阻塞到同步事件分离器上有事件产生为止。对于Linux来说,同步事件分离器指的就是常用的I/O多路复用机制,比如说select、poll、epoll等。在Java NIO领域中,同步事件分离器对应的组件就是Selector;对应的阻塞方法就是select方法。
  • Event Handler(事件处理器):本身由多个回调方法构成,这些回调方法构成了与应用相关的对于某个事件的反馈机制。在Java NIO领域中并没有提供事件处理器机制让我们调用或去进行回调,是由我们自己编写代码完成的。Netty相比于Java NIO来说,在事件处理器这个角色上进行了一个升级,它为我们开发者提供了大量的回调方法,供我们在特定事件产生时实现相应的回调方法进行业务逻辑的处理,即,ChannelHandler。ChannelHandler中的方法对应的都是一个个事件的回调。
  • Concrete Event Handler(具体事件处理器):是事件处理器的实现。它本身实现了事件处理器所提供的各种回调方法,从而实现了特定于业务的逻辑。它本质上就是我们所编写的一个个的处理器实现。
  • Initiation Dispatcher(初始分发器):实际上就是Reactor角色。它本身定义了一些规范,这些规范用于控制事件的调度方式,同时又提供了应用进行事件处理器的注册、删除等设施。它本身是整个事件处理器的核心所在,Initiation Dispatcher会通过Synchronous Event Demultiplexer来等待事件的发生。一旦事件发生,Initiation Dispatcher首先会分离出每一个事件,然后调用事件处理器,最后调用相关的回调方法来处理这些事件。Netty中ChannelHandler里的一个个回调方法都是由bossGroup或workGroup中的某个EventLoop来调用的。

2.3 Reactor模式的经典实现—Netty

Netty的线程模式就是一个实现了Reactor模式的经典模式。

  • 结构对应:
    NioEventLoop ———— Initiation Dispatcher
    Synchronous EventDemultiplexer ———— Selector
    Evnet Handler ———— ChannelHandler
    ConcreteEventHandler ———— 具体的ChannelHandler的实现

  • 模式对应:
    Netty服务端使用了“多Reactor线程模式”
    mainReactor ———— bossGroup(NioEventLoopGroup) 中的某个NioEventLoop
    subReactor ———— workerGroup(NioEventLoopGroup) 中的某个NioEventLoop
    acceptor ———— ServerBootstrapAcceptor
    ThreadPool ———— 用户自定义线程池

  • 流程:
    ① 当服务器程序启动时,会配置ChannelPipeline,ChannelPipeline中是一个ChannelHandler链,所有的事件发生时都会触发Channelhandler中的某个方法,这个事件会在ChannelPipeline中的ChannelHandler链里传播。然后,从bossGroup事件循环池中获取一个NioEventLoop来现实服务端程序绑定本地端口的操作,将对应的ServerSocketChannel注册到该NioEventLoop中的Selector上,并注册ACCEPT事件为ServerSocketChannel所感兴趣的事件。
    ② NioEventLoop事件循环启动,此时开始监听客户端的连接请求。
    ③ 当有客户端向服务器端发起连接请求时,NioEventLoop的事件循环监听到该ACCEPT事件,Netty底层会接收这个连接,通过accept()方法得到与这个客户端的连接(SocketChannel),然后触发ChannelRead事件(即,ChannelHandler中的channelRead方法会得到回调),该事件会在ChannelPipeline中的ChannelHandler链中执行、传播。
    ④ ServerBootstrapAcceptor的readChannel方法会该SocketChannel(客户端的连接)注册到workerGroup(NioEventLoopGroup) 中的某个NioEventLoop的Selector上,并注册READ事件为SocketChannel所感兴趣的事件。启动SocketChannel所在NioEventLoop的事件循环,接下来就可以开始客户端和服务器端的通信了。

3 Spring5中多Reactive的支持

3.1 Spring Webflux

3.1.1 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
3.1.2 Controller代码
@RestController
public class HelloController {@GetMapping("/hello")public Mono<String> hello() {return Mono.just("Hello Spring Webflux");}}
3.1.3 测试
C:\Users\xxxx\Desktop\sb-reactive>curl http://localhost:8080/hello
Hello Spring Webflux
3.1.4 Spring MVC和Spring WebFlux模式上的不同

3.2 Spring Data Reactive Respositories

3.2.1 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>
3.2.2 配置
public class RedisReactiveConfig {@Beanpublic ReactiveRedisConnectionFactory connectionFactory() {return new LettuceConnectionFactory("127.0.0.1", 6379);}@Beanpublic ReactiveStringRedisTemplate reactiveStringRedisTemplate(ReactiveRedisConnectionFactory factory) {return new ReactiveStringRedisTemplate(factory);}}
3.3.3 测试
@SpringBootTest
class SbReactiveApplicationTests {@Autowiredprivate ReactiveStringRedisTemplate reactiveRedisTemplate;@Testvoid contextLoads() {reactiveRedisTemplate.opsForValue().set("1", "zs").subscribe(b -> System.out.println("success"),e -> System.out.println("error"));}}

4 最后一问:如何理解Reactive响应式编程?

概念有很多,但是它相较我们的一般请求处理到底有什么更好的价值体现?

以下是来自小马哥的一段解释:

Reactive Programming 作为观察者模式(Observer) 的延伸,不同于传统的命令编程方式( Imperative programming)同步拉取数据的方式,如迭代器模式(Iterator) 。而是采用数据发布者同步或异步地推送到数据流(Data Streams)的方案。当该数据流(Data Steams)订阅者监听到传播变化时,立即作出响应动作。在实现层面上,Reactive Programming 可结合函数式编程简化面向对象语言语法的臃肿性,屏蔽并发实现的复杂细节,提供数据流的有序操作,从而达到提升代码的可读性,以及减少 Bugs 出现的目的。同时,Reactive Programming 结合背压(Backpressure)的技术解决发布端生成数据的速率高于订阅端消费的问题。

参考文章:

https://www.jianshu.com/p/1765f658200a

https://blog.csdn.net/get_set/article/details/79480233

https://zh.wikipedia.org/wiki/%E5%93%8D%E5%BA%94%E5%BC%8F%E7%BC%96%E7%A8%8B

https://zh.wikipedia.org/wiki/Reactor

https://www.cnblogs.com/shujiying/p/12386505.html

https://www.cnblogs.com/littleatp/p/11515458.html

https://www.cnblogs.com/lucky9322/p/13533769.html

https://www.imooc.com/article/46306

玩转Spring—Spring5新特性之Reactive响应式编程实战相关推荐

  1. Reactive 响应式编程简单使用

    Reactive Stream 模型 了解reactive stream(Flow类) 在介绍java版本的reactive stream之前,我们先回顾一下reactive stream需要做哪些事 ...

  2. Java8新特性之Stream流式编程

    特地感谢鲁班大叔的分享,原学习地址:Java8 Stream流式编程爱 撸码就是快,流式编程好 代码传家宝 以下是学习过程整理的笔记 1.简介 Stream 流处理,首先要澄清的是 java8 中的 ...

  3. 浅谈Spring5 响应式编程

    目录 为什么是响应式编程 用于响应式编程实现的理想案例 响应流 (Reactive Streams) Spring 5 提供的响应式编程 Spring Web Reactive vs. Spring ...

  4. Reactive(1) 从响应式编程到好莱坞

    目录 概念 面向流设计 异步化 响应式宣言 参考文档 概念 Reactive Programming(响应式编程)已经不是一个新东西了. 关于 Reactive 其实是一个泛化的概念,由于很抽象,一些 ...

  5. spring5新特性的介绍

    Spring5的新特性 与JDK相关的升级 jdk版本要求: spring5.0在2017年9月发布了它的GA(通用)版本.该版本是基于jdk8编写的,所以jdk8以下版本将无法使用.同时,可以兼容j ...

  6. Spring5 新特性

    Spring5 新特性 Spring 5于2017年底发布.Spring 5为Spring框架带来了大量更新.Spring 4于2013年发布,因此每个人都期待对该框架进行重大改革.我很高兴看到Spr ...

  7. 未来:spring响应式编程 Hands-On Reactive Programming in Spring 5 ,为啥需要响应式编程

    Why Reactive Spring? 为什么 使用响应式 的spring In this chapter, we are going to explain the concept of react ...

  8. 未来:spring响应式编程 Hands-On Reactive Programming in Spring 5(二)------Basic Concepts

    看完这篇文章你会有很大收获! 好学近乎知,力行近乎仁,知耻而后勇. The previous chapter explained why it is important to build reacti ...

  9. Reactive响应式流入门

    再谈响应式 在前一篇文章 从Reactive编程到"好莱坞" 中,谈到了响应式的一些概念,讲的有些发散.但仅仅还是停留在概念的层面,对于实战性的东西并没有涉及.所以大家看了后,或许 ...

最新文章

  1. Tornado、Bottle以及Flask
  2. HDLBits答案(10)_D触发器、同步与异步复位、脉冲边沿检测
  3. IDEA git修改远程仓库地址
  4. [mybatis]Mapper XML Files_获取自增主键的值
  5. @service注解_Spring 中 @Component、@Service 等注解如何被解析?
  6. 十年技术骨干面试被开出一万五薪资,直呼 “这是对我的侮辱”
  7. CF567E President and Roads
  8. linux更换域名全站301,linux服务器wdcp面板做301域名重定向设置
  9. 如何在微博侧栏中加入自己的微博[js]
  10. 【大数据部落】基于ARIMA、SVM、随机森林销售的时间序列预测
  11. Notepad3(高级文本编辑器)v5.19.815.2595版本更新啦
  12. 空间解析几何之向量运算
  13. 基于哈夫曼编码的文件压缩
  14. unity reflect_Unity Reflect在这里
  15. 论文阅读《PatchMatchNet: Learned Multi-View Patchmatch Stereo》
  16. java-php-python-ssm智能健身房管理计算机毕业设计
  17. Django实现websocket聊天室
  18. 评估期已过.有关如何升级您的测试版软件的信息,请访问,sql server 2008 r2评估期已过。有关如何升级的测试版软件的信息...
  19. WPS网盘怎么显示在我的电脑里?
  20. 原生JS 和 jQuery 通过url传递 和 接收 自定义参数

热门文章

  1. 写出漂亮的Markdown文档_v1.0.6
  2. 大学生医用计算机题库,大学生计算机考题题库.doc
  3. 基于单片机的电子钟程序设计与调试
  4. 第八届蓝桥杯单片机省赛----程序题
  5. java实训手册_JAVA实训项目用户手册.doc
  6. 苹果手机怎么下载python123_苹果手机怎么下载端游吃鸡
  7. 关于助焊层和阻焊层的理解
  8. MySQL报错1406_MySQL #1406 Data too long错误
  9. 增大肌肉块-14大金律
  10. Java EE知识体系