Reactive Streams, flux, mono介绍之白话版

本文介绍了Reactive Streams如何解决高并发下数据流交互的背压问题,通过发布者Publisher、订阅者Subscriber和订阅对象Subscription等核心概念进行解释。文章还探讨了Spring WebFlux中的响应式流应用,包括服务端技术和响应式Http客户端WebClient的使用方法。

目录

要解决的问题:

解决原理:

解决方法:

          发布者Publisher

          订阅者Subscriber

          订阅对象Subscription

          处理者Processor

源码简析

spring中响应式流的应用

 服务端技术栈

 响应式Http客户端

服务端修改

客户端webClient的使用方法


 

 

响应式流(Reactive Streams)是以带非阻塞背压方式处理异步数据流的标准,提供一组最小化的接口,方法和协议来描述必要的操作和实体。

要解决的问题:

系统之间高并发的大量数据流交互通常采用异步的发布-订阅模式。数据由发布者推送给订阅者的过程中,容易产生的一个问题是,当发布者即生产者产生的数据速度远远大于订阅者即消费者的消费速度时,消费者会承受巨大的资源压力(pressure)而有可能崩溃。

解决原理:

为了解决以上问题,数据流的速度需要被控制,即流量控制(flow control),以防止快速的数据流不会压垮目标。因此需要反压即背压(back pressure),生产者和消费者之间需要通过实现一种背压机制来互操作。实现这种背压机制要求是异步非阻塞的,如果是同步阻塞的,消费者在处理数据时生产者必须等待,会产生性能问题。

解决方法:

响应式流(Reactive Streams)通过定义一组实体,接口和互操作方法,给出了实现非阻塞背压的标准。第三方遵循这个标准来实现具体的解决方案,常见的有Reactor,RxJava,Akka Streams,Ratpack等。

该标准定义了四个接口:

 

  • 发布者Publisher

interface Publisher<T> {
 void subscribe(Subscriber<? super T> subscriber);
}

发布者只有一个方法,用来接受订阅者进行订阅(subscribe)。T代表发布者和订阅者之间传输的数据类型。它有两个实现类,Flux<T>和Mono<T>。通俗理解就是Flux可以触发零到多个事件。Mono最多只触发一个事件。

 

  • 订阅者Subscriber

interface Subscriber<T> {
 void onSubscribe(Subscription s);
 void onNext(T t);
 void onError(Throwable t);
 void onComplete();
}

订阅者有四个事件方法,分别在开启订阅、接收数据、发生错误和数据传输结束时被调用。

 

  • 订阅对象Subscription

interface Subscription {
 void request(long n);
 void cancel();
}

 

  • 处理者Processor

interface Processor<T,R> extends Subscriber<T>, Publisher<R> {
}

处理者既是发布者又是订阅者,用于在发布者和订阅者之间转换数据格式,把发布者的R类型数据转换为订阅者接受的T类型数据。处理者作为数据转换的中介不是必须的。

由以上的接口可以看出,核心在于订阅者可以通过request(long n)方法来控制接收的数据量,达到了实现背压的目的。

 

 

概念太抽象,举个栗子吧:

@Test
public void testBackpressure() {
    Flux.just("one","two").log().subscribe(new SubscriberImpl());
}

class SubscriberImpl implements Subscriber<String> {

    @Override
    public void onSubscribe(Subscription s) {
        s.request(1);
    }

    @Override
    public void onNext(String s) {
        System.out.println(s);
    }

    @Override
    public void onError(Throwable t) {
    }

    @Override
    public void onComplete() {
        System.out.println("done");
    }
}

来看上面的例子,订阅对象(Subscription  s)是发布者(Flux)和订阅者之间交互的操作对象,在发布者(Flux)通过subscribe方法加入订阅者时,会通过调用订阅者(Subscriber)的onSubscribe把订阅对象(Subscription)传给订阅者(Subscriber)。

订阅者(Subscriber)拿到订阅对象(Subscription)后,通过调用订阅对象的request方法,根据自身消费能力请求n条数据,或者调用cancel方法来停止接收数据(当调用cancel方法后则不会进行消费)。

订阅对象的request方法被调用时,会触发订阅者的onNext事件方法,把数据传输给订阅者。如果数据全部传输完成,则触发订阅者的onComplete事件方法。如果数据传输发生错误,则触发订阅者的onError事件方法。

 

log()方法顾名思义就是增加日志打印,上面的代码运行后输出如下:


                
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值