Spring Reactive,spring5响应式编程能火吗
00-1010 1什么是响应式编程2反应器2.1复习什么是反应器2.2,为什么是反应器2.3的经典实现?Netty 3 Spring 5 3.1 Spring webflux 3 . 1 . 1中对多反应性的支持依赖于3.1.2控制器代码3。1.3测试3 . 1 . 4 Spring MVC和Spring WebFlux模式的区别3.2 spring数据反应式响应3.2.1依赖3.2.2配置3.3.3测试4如何理解反应式编程?
00-1010一句话总结:响应式编程是一种编程范式,通用且专注于数据流和变化,并且异步。
维基百科原文:
在计算中,反应式编程是一种与数据流和变化传播有关的异步编程范例。这意味着可以通过所采用的编程语言轻松地表达静态(例如数组)或动态(例如事件发射器)数据流,并且在相关联的执行模型内存在推断的依赖性,这有助于数据流所涉及的变化的自动传播。
翻译:
在计算机领域,响应式编程(responsive programming)是一种* *异步编程范式,专注于数据流和变化传输。* *这意味着静态(例如,数组)或动态(例如,事件发射器)数据流可以容易地使用编程语言来表示,并且在相关联的执行模型中,存在推断的依赖关系,该依赖关系的存在有助于自动传播与数据流相关的改变。
举例:
比如在命令式编程环境中,a:=b c表示将表达式的结果赋给A,然后改变B或C的值不会对其产生影响。但在响应式编程中,A的值会随着B或c的更新而更新,电子表格程序就是响应式编程的一个例子。单元格可以包含文字值或公式,如“=B1 C1”,包含公式的单元格的值将根据其他单元格的值而变化。
响应式编程最初是为了简化交互式用户界面的创建和实时系统动画的绘制而提出的,但它本质上是一种通用的编程范式。
目录
1 什么是响应式编程
还是维基百科:
反应器设计模式是一种事件处理模式,用于处理通过一个或多个输入并发传递给服务处理程序的服务请求。然后,服务处理程序对传入的请求进行解复用,并将它们同步分派给相关的请求处理程序。
翻译:
反应器设计模式是一种事件处理模式,用于处理通过一个或多个输入传递给服务处理程序的服务请求。然后,服务处理程序对传入的请求进行解复用,并将它们同步分派给相关的请求处理程序。
2 回顾Reactor
Reactor来源于网络IO中同步无阻塞I/O复用机制的模式。
拥塞和非拥塞的区别在于第一阶段,即数据准备阶段。无论是否被阻塞,应用程序都主动向内核请求数据,读取数据的过程被‘阻塞’直到数据被读取。同步和异步的区别在于第二个阶段。如果请求者主动获取数据,就是同步操作。应当注意,读/写操作也被“阻止”,直到数据被读取。如果数据读取由内核kernel完成(在内核读取数据的同时,应用程序进程仍然可以执行其他任务。
务),这就是异步操作。
换句话说,
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 DispatcherSynchronous EventDemultiplexer ———— SelectorEvnet Handler ———— ChannelHandlerConcreteEventHandler ———— 具体的ChannelHandler的实现
模式对应:
Netty服务端使用了多Reactor线程模式mainReactor ———— bossGroup(NioEventLoopGroup) 中的某个NioEventLoopsubReactor ———— workerGroup(NioEventLoopGroup) 中的某个NioEventLoopacceptor ———— ServerBootstrapAcceptorThreadPool ———— 用户自定义线程池
流程:
① 当服务器程序启动时,会配置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代码
@RestControllerpublic class HelloController { @GetMapping("/hello") public Mono<String> hello() { return Mono.just("Hello Spring Webflux"); } }
3.1.3 测试
C:UsersxxxxDesktopsb-reactive>curl http://localhost:8080/helloHello 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 测试
@SpringBootTestclass 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响应式编程内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。