Spring5新特性之Reactive响应式编程

目录
  • 1什么是响应式编程
  • 2回顾Reactor
    • 2.1什么是Reactor
    • 2.2为什么是Reactor
    • 2.3Reactor模式的经典实现—Netty
  • 3Spring5中多Reactive的支持
    • 3.1SpringWebflux
      • 3.1.1依赖
      • 3.1.2Controller代码
      • 3.1.3测试
      • 3.1.4SpringMVC和SpringWebFlux模式上的不同
    • 3.2SpringDataReactiveRespositories
      • 3.2.1依赖
      • 3.2.2配置
      • 3.3.3测试
  • 4如何理解Reactive响应式编程?

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 ———— 用户自定义线程池

流程:

① 当服务器程序启动时,会配置ChannelPipelineChannelPipeline中是一个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 {

    @Bean
    public ReactiveRedisConnectionFactory connectionFactory() {
        return new LettuceConnectionFactory("127.0.0.1", 6379);
    }

    @Bean
    public ReactiveStringRedisTemplate reactiveStringRedisTemplate(ReactiveRedisConnectionFactory factory) {
        return new ReactiveStringRedisTemplate(factory);
    }

}

3.3.3 测试

@SpringBootTest
class SbReactiveApplicationTests {

    @Autowired
    private ReactiveStringRedisTemplate reactiveRedisTemplate;

    @Test
    void 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)的技术解决发布端生成数据的速率高于订阅端消费的问题。

到此这篇关于Spring5新特性之Reactive响应式编程的文章就介绍到这了,更多相关Reactive响应式编程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud 服务注册中的nacos实现过程

    如下图,org.springframework.cloud.spring-cloud-commons包下定义了一系列接口,其中就包括serviceregistry的系列规范,并通过SPI机制去调用接口实现. 在该包的META-INF/spring.factories文件中,可以找到EnableAutoConfiguration.class为key的value中有AutoServiceRegistrationAutoConfiguration.class这一项. 来看看这个AutoServiceR

  • Springboot整合Dozer实现深度复制的方法

    目录 Dozer SpringBoot整合Dozer jar依赖引入 dozer配置xml引入 Dozer的JavaConfig 格式化工厂 使用Demo Dozer Dozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵活的,可重用的和可配置的开源映射框架. 常用于: 代码层与层之间javabean转换, 如dao层PO转前端VO 分布式中, DAO层PO转DTO, DO 以及web层DTO转VO 注意的场景: 由于b

  • SpringBoot中Dozer的使用小结

    什么是Dozer? Dozer是一种Java Bean到Java Bean的映射器,递归地将数据从一个对象复制到另一个对象,它是一个强大的,通用的,灵活的,可重用的和可配置的开源映射框架.说白点就是dozer是一个能把实体和实体之间进行转换的工具.只要建立好映射关系.就像是ORM的数据库和实体映射一样. dozer是用来两个对象之间属性转换的工具,有了这个工具之后,我们将一个对象的所有属性值转给另一个对象时,就不需要再去写重复的set和get方法了. 下面我们来学习一下dozer的使用 1.添加

  • setup+ref+reactive实现vue3响应式功能

    setup 是用来写组合式 api ,内部的数据和方法需要通过 return 之后,模板才能使用.在之前 vue2 中,data 返回的数据,可以直接进行双向绑定使用,如果我们把 setup 中数据类型直接双向绑定,发现变量并不能实时响应.接下来就看看setup如何实现data的响应式功能? 一.ref setup 内的自定义属性不具备响应式能力,所以引入了 ref ,ref 底层通过代理,把属性包装值包装成一个 proxy ,proxy 内部是一个对象,使得基础类型的数据具备响应式能力,使用之

  • Spring5新特性之Reactive响应式编程

    目录 1什么是响应式编程 2回顾Reactor 2.1什么是Reactor 2.2为什么是Reactor 2.3Reactor模式的经典实现—Netty 3Spring5中多Reactive的支持 3.1SpringWebflux 3.1.1依赖 3.1.2Controller代码 3.1.3测试 3.1.4SpringMVC和SpringWebFlux模式上的不同 3.2SpringDataReactiveRespositories 3.2.1依赖 3.2.2配置 3.3.3测试 4如何理解R

  • 一文带你搞懂Spring响应式编程

    目录 1. 前言 1.1 常用函数式编程 1.2 Stream操作 2. Java响应式编程 带有中间处理器的响应式流 3. Reactor 3.1 Flux & Mono 3.2 Flux Mono创建与使用 4. WebFlux Spring WebFlux示例 基于注解的WebFlux 基于函数式编程的WebFlux Flux与Mono的响应式编程延迟示例 总结 哈喽,大家好,我是指北君. 相信响应式编程经常会在各种地方被提到.本篇就为大家从函数式编程一直到Spring WeFlux做一次

  • java9新特性Reactive Stream响应式编程 API

    目录 一.Java9ReactiveStreamAPI 二.Java响应式编程四大接口 2.1.SubscriberInterface(订阅者订阅接口) 2.2.SubscriptionInterface(订阅令牌接口) 2.3.PublisherInterface(发布者接口) 2.4.ProcessorInterface(处理器接口) 二.实战案例 实现订阅者SubscriberInterface SubmissionPublisher消息发布者 我计划在后续的一段时间内,写一系列关于jav

  • java9新特性Reactive Stream响应式编程 API

    目录 一.Java9ReactiveStreamAPI 二.Java响应式编程四大接口 2.1.SubscriberInterface(订阅者订阅接口) 2.2.SubscriptionInterface(订阅令牌接口) 2.3.PublisherInterface(发布者接口) 2.4.ProcessorInterface(处理器接口) 二.实战案例 实现订阅者SubscriberInterface SubmissionPublisher消息发布者 我计划在后续的一段时间内,写一系列关于jav

  • 浅谈Spring5 响应式编程

    近年来,响应式编程在开发者社区和客户中很受欢迎,由于其以声明的方式构建应用程序的能力,而不是强制,形成更加敏感和有弹性的应用.Spring 5 将反应系统纳入其核心框架的事实已经显示出向声明式编程的范式转变. 响应式编程管理数据生产者和消费者之间的异步数据流,它们需要以流畅的方式对数据进行响应.所以,响应式编程都是异步和事件驱动的流畅应用程序,需要少量的线程进行缩放. 响应式编程很难构建基于线程的架构,由于在基于共享可变状态.线程和锁的应用程序扩展过程中涉及到高度复杂性. 在响应式编程的上下文中

  • spring5新特性全面介绍

    前方:对于很多开发人员来说,目前大都还在使用spring4的时候,而spring5早已经发布.虽然你可能暂时还没有使用到spring5,但还是需要对其有个大概的了解. Spring 5 于 2017 年 9 月发布了通用版本 (GA),它标志着自 2013 年 12 月以来第一个主要 Spring Framework 版本.它提供了一些人们期待已久的改进,还采用了一种全新的编程范例,以反应式宣言中陈述的反应式原则为基础. 这个版本是很长时间以来最令人兴奋的 Spring Framework 版本

  • Reactive反应式编程及使用介绍

    目录 前言 反应式编程简介 阻塞可能会浪费资源 使用异步来解决? 回调地狱的例子 与回调代码等效的Reactor代码示例 具有超时和回退的Reactor代码示例 CompletableFuture组合的例子 与未来代码等效的Reactor代码示例 从命令式到反应式编程 可组合性和可读性 类比装配线工作流程 操作符(运算符) 在你订阅之前什么都不会发生 背压 热与冷 前言 前一篇分析了Spring WebFlux的设计及实现原理后,反应式编程又来了,Spring WebFlux其底层还是基于Rea

  • 利用Swift实现一个响应式编程库

    前言 整个2017年我完全使用 Swift 进行开发了.使用 Swift 进行开发是一个很愉快的体验,我已经完全不想再去碰 OC 了.最近想做一个响应式编程的库,所以就把它拿来分享一下. 在缺乏好的资源的情况下,学习响应式编程成为痛苦.我开始学的时候,做死地找各种教程.结果发现有用的只是极少部分,而且这少部分也只是表面上的东西,对于整个体系结构的理解也起不了多大的作用. Reactive Programing 说到响应式编程,ReactiveCocoa 和 RxSwift 可以说是目前 iOS

  • 关于springboot响应式编程整合webFlux的问题

    在servlet3.0标准之前,是每一个请求对应一个线程.如果此时一个线程出现了高延迟,就会产生阻塞问题,从而导致整个服务出现严重的性能情况,因为一旦要调用第三方接口,就有可能出现这样的操作了.早期的处理方式只能是手工控制线程. 在servlet3.0标准之后,为了解决此类问题,所以提供了异步响应的支持.在异步响应处理结构中,可以将耗时操作的部分交由一个专属的异步线程进行响应处理,同时请求的线程资源将被释放,并将该线程返回到线程池中,以供其他用户使用,这样的操作机制将极大的提升程序的并发性能.

  • springboot3+r2dbc响应式编程实践

    目录 r2dbc 工程依赖 配置文件 配置类 bean DAO controller Spring boot3已经M1了,最近群佬们也开始蠢蠢欲动的开始整活Reactive+Spring Boot3,跟着大家的步伐,我也来整一篇工程入门,我们将用java17+Spring Boot3+r2dbc+Reactive栈来讲述,欢迎大家来讨论.(关于响应式,请大家异步到之前的文章里,有详细介绍.) r2dbc Reactor还有基于其之上的Spring WebFlux框架.包括vert.x,rxjav

随机推荐